[FE 1.0] Add NativeObjCRefinement checkers
This commit is contained in:
committed by
SvyatoslavScherbina
parent
6ae517a2df
commit
203af3afdd
@@ -0,0 +1,131 @@
|
||||
// FILE: kotlin.kt
|
||||
package kotlin.native
|
||||
|
||||
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@MustBeDocumented
|
||||
annotation class HidesFromObjC
|
||||
|
||||
@HidesFromObjC
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class HiddenFromObjC
|
||||
|
||||
@Target(AnnotationTarget.ANNOTATION_CLASS)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class RefinesInSwift
|
||||
|
||||
@RefinesInSwift
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
public annotation class ShouldRefineInSwift
|
||||
|
||||
// FILE: plugin.kt
|
||||
package plugin
|
||||
|
||||
@HidesFromObjC
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class PluginHiddenFromObjC
|
||||
|
||||
@RefinesInSwift
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class PluginShouldRefineInSwift
|
||||
|
||||
// FILE: test.kt
|
||||
import plugin.PluginHiddenFromObjC
|
||||
import plugin.PluginShouldRefineInSwift
|
||||
|
||||
@HidesFromObjC
|
||||
<!REDUNDANT_SWIFT_REFINEMENT!>@RefinesInSwift<!>
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class MyRefinedAnnotationA
|
||||
|
||||
<!INVALID_OBJC_REFINEMENT_TARGETS!>@HidesFromObjC<!>
|
||||
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class MyRefinedAnnotationB
|
||||
|
||||
<!INVALID_OBJC_REFINEMENT_TARGETS!>@RefinesInSwift<!>
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class MyRefinedAnnotationC
|
||||
|
||||
@RefinesInSwift
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class MyRefinedAnnotationD
|
||||
|
||||
@HiddenFromObjC
|
||||
<!REDUNDANT_SWIFT_REFINEMENT!>@ShouldRefineInSwift<!>
|
||||
var refinedProperty: Int = 0
|
||||
|
||||
@PluginHiddenFromObjC
|
||||
<!REDUNDANT_SWIFT_REFINEMENT!>@PluginShouldRefineInSwift<!>
|
||||
fun pluginRefinedFunction() { }
|
||||
|
||||
@HiddenFromObjC
|
||||
@PluginHiddenFromObjC
|
||||
fun multipleObjCRefinementsFunction() { }
|
||||
|
||||
@ShouldRefineInSwift
|
||||
@PluginShouldRefineInSwift
|
||||
fun multipleSwiftRefinementsFunction() { }
|
||||
|
||||
@HiddenFromObjC
|
||||
@PluginHiddenFromObjC
|
||||
<!REDUNDANT_SWIFT_REFINEMENT!>@ShouldRefineInSwift<!>
|
||||
<!REDUNDANT_SWIFT_REFINEMENT!>@PluginShouldRefineInSwift<!>
|
||||
fun multipleMixedRefinementsFunction() { }
|
||||
|
||||
interface InterfaceA {
|
||||
val barA: Int
|
||||
val barB: Int
|
||||
fun fooA()
|
||||
@HiddenFromObjC
|
||||
fun fooB()
|
||||
}
|
||||
|
||||
interface InterfaceB {
|
||||
val barA: Int
|
||||
@ShouldRefineInSwift
|
||||
val barB: Int
|
||||
@HiddenFromObjC
|
||||
fun fooA()
|
||||
@HiddenFromObjC
|
||||
fun fooB()
|
||||
}
|
||||
|
||||
open class ClassA: InterfaceA, InterfaceB {
|
||||
<!INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE!>@HiddenFromObjC<!>
|
||||
override val barA: Int = 0
|
||||
<!INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE!>@ShouldRefineInSwift<!>
|
||||
override val barB: Int = 0
|
||||
<!INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE!>override fun fooA() { }<!>
|
||||
override fun fooB() { }
|
||||
@HiddenFromObjC
|
||||
open fun fooC() { }
|
||||
}
|
||||
|
||||
class ClassB: ClassA() {
|
||||
@HiddenFromObjC
|
||||
override fun fooB() { }
|
||||
<!INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE!>@ShouldRefineInSwift<!>
|
||||
override fun fooC() { }
|
||||
}
|
||||
|
||||
open class Base {
|
||||
@HiddenFromObjC
|
||||
open fun foo() {}
|
||||
}
|
||||
|
||||
interface I {
|
||||
fun foo()
|
||||
}
|
||||
|
||||
<!INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE!>open class Derived : Base(), I<!>
|
||||
|
||||
open class Derived2 : Derived() {
|
||||
override fun foo() {}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package
|
||||
|
||||
@kotlin.native.HiddenFromObjC @kotlin.native.ShouldRefineInSwift public var refinedProperty: kotlin.Int
|
||||
@kotlin.native.HiddenFromObjC @plugin.PluginHiddenFromObjC @kotlin.native.ShouldRefineInSwift @plugin.PluginShouldRefineInSwift public fun multipleMixedRefinementsFunction(): kotlin.Unit
|
||||
@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 open class Base {
|
||||
public constructor Base()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
@kotlin.native.HiddenFromObjC public open fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class ClassA : InterfaceA, InterfaceB {
|
||||
public constructor ClassA()
|
||||
@kotlin.native.HiddenFromObjC public open override /*2*/ val barA: kotlin.Int = 0
|
||||
@kotlin.native.ShouldRefineInSwift public open override /*2*/ val barB: kotlin.Int = 0
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ fun fooA(): kotlin.Unit
|
||||
public open override /*2*/ fun fooB(): kotlin.Unit
|
||||
@kotlin.native.HiddenFromObjC public open fun fooC(): kotlin.Unit
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class ClassB : ClassA {
|
||||
public constructor ClassB()
|
||||
@kotlin.native.HiddenFromObjC public open override /*1*/ /*fake_override*/ val barA: kotlin.Int
|
||||
@kotlin.native.ShouldRefineInSwift public open override /*1*/ /*fake_override*/ val barB: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun fooA(): kotlin.Unit
|
||||
@kotlin.native.HiddenFromObjC public open override /*1*/ fun fooB(): kotlin.Unit
|
||||
@kotlin.native.ShouldRefineInSwift public open override /*1*/ fun fooC(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class Derived : Base, I {
|
||||
public constructor Derived()
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
@kotlin.native.HiddenFromObjC public open override /*2*/ /*fake_override*/ fun foo(): kotlin.Unit
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class Derived2 : Derived {
|
||||
public constructor Derived2()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ fun foo(): kotlin.Unit
|
||||
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
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface InterfaceA {
|
||||
public abstract val barA: kotlin.Int
|
||||
public abstract val barB: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun fooA(): kotlin.Unit
|
||||
@kotlin.native.HiddenFromObjC public abstract fun fooB(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface InterfaceB {
|
||||
public abstract val barA: kotlin.Int
|
||||
@kotlin.native.ShouldRefineInSwift public abstract val barB: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
@kotlin.native.HiddenFromObjC public abstract fun fooA(): kotlin.Unit
|
||||
@kotlin.native.HiddenFromObjC public abstract fun fooB(): kotlin.Unit
|
||||
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
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
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 {
|
||||
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
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.native.RefinesInSwift @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class MyRefinedAnnotationC : kotlin.Annotation {
|
||||
public constructor MyRefinedAnnotationC()
|
||||
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.RefinesInSwift @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class MyRefinedAnnotationD : kotlin.Annotation {
|
||||
public constructor MyRefinedAnnotationD()
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.ANNOTATION_CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) @kotlin.annotation.MustBeDocumented public final annotation class HidesFromObjC : kotlin.Annotation {
|
||||
public constructor HidesFromObjC()
|
||||
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.annotation.Target(allowedTargets = {AnnotationTarget.ANNOTATION_CLASS}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class RefinesInSwift : kotlin.Annotation {
|
||||
public constructor RefinesInSwift()
|
||||
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.RefinesInSwift @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class ShouldRefineInSwift : kotlin.Annotation {
|
||||
public constructor ShouldRefineInSwift()
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.native.RefinesInSwift @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final annotation class PluginShouldRefineInSwift : kotlin.Annotation {
|
||||
public constructor PluginShouldRefineInSwift()
|
||||
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
|
||||
}
|
||||
}
|
||||
+6
@@ -36,6 +36,12 @@ public class DiagnosticsNativeTestGenerated extends AbstractDiagnosticsNativeTes
|
||||
runTest("compiler/testData/diagnostics/nativeTests/objCName.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("objCRefinement.kt")
|
||||
public void testObjCRefinement() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/nativeTests/objCRefinement.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("sharedImmutable.kt")
|
||||
public void testSharedImmutable() throws Exception {
|
||||
|
||||
+11
@@ -54,6 +54,17 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
||||
put(ErrorsNative.INAPPLICABLE_EXACT_OBJC_NAME, "Exact @ObjCName is only applicable to classes, objects and interfaces")
|
||||
put(ErrorsNative.MISSING_EXACT_OBJC_NAME, "Exact @ObjCName is required to have an ObjC name")
|
||||
put(ErrorsNative.NON_LITERAL_OBJC_NAME_ARG, "@ObjCName accepts only literal string and boolean values")
|
||||
put(ErrorsNative.REDUNDANT_SWIFT_REFINEMENT, "An ObjC refined declaration can't also be refined in Swift")
|
||||
put(
|
||||
ErrorsNative.INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE,
|
||||
"Refined declaration \"{0}\" overrides declarations with different or no refinement from {1}",
|
||||
Renderers.NAME,
|
||||
CommonRenderers.commaSeparated(Renderers.NAME)
|
||||
)
|
||||
put(
|
||||
ErrorsNative.INVALID_OBJC_REFINEMENT_TARGETS,
|
||||
"Refines annotations are only applicable to annotations with targets FUNCTION and/or PROPERTY"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,8 +52,14 @@ object ErrorsNative {
|
||||
val MISSING_EXACT_OBJC_NAME = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
|
||||
@JvmField
|
||||
val NON_LITERAL_OBJC_NAME_ARG = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
|
||||
@JvmField
|
||||
val REDUNDANT_SWIFT_REFINEMENT = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
|
||||
@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)
|
||||
|
||||
init {
|
||||
Errors.Initializer.initializeFactoryNames(ErrorsNative::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.resolve.konan.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
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
|
||||
|
||||
object NativeObjCRefinementAnnotationChecker : DeclarationChecker {
|
||||
|
||||
private val supportedTargets = 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()
|
||||
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
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.resolve.konan.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
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.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.konan.diagnostics.NativeObjCRefinementOverridesChecker.check
|
||||
|
||||
object NativeObjCRefinementChecker : DeclarationChecker {
|
||||
|
||||
val hidesFromObjCFqName = FqName("kotlin.native.HidesFromObjC")
|
||||
val refinesInSwiftFqName = FqName("kotlin.native.RefinesInSwift")
|
||||
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (descriptor !is CallableMemberDescriptor) return
|
||||
if (descriptor !is FunctionDescriptor && descriptor !is PropertyDescriptor) return
|
||||
val (objCAnnotations, swiftAnnotations) = descriptor.findRefinedAnnotations()
|
||||
if (objCAnnotations.isNotEmpty() && swiftAnnotations.isNotEmpty()) {
|
||||
swiftAnnotations.forEach {
|
||||
val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(it) ?: declaration
|
||||
context.trace.report(ErrorsNative.REDUNDANT_SWIFT_REFINEMENT.on(reportLocation))
|
||||
}
|
||||
}
|
||||
check(declaration, descriptor, context, objCAnnotations, swiftAnnotations)
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.findRefinedAnnotations(): Pair<List<AnnotationDescriptor>, List<AnnotationDescriptor>> {
|
||||
val objCAnnotations = mutableListOf<AnnotationDescriptor>()
|
||||
val swiftAnnotations = mutableListOf<AnnotationDescriptor>()
|
||||
for (annotation in annotations) {
|
||||
val annotations = annotation.annotationClass?.annotations ?: continue
|
||||
for (metaAnnotation in annotations) {
|
||||
when (metaAnnotation.fqName) {
|
||||
hidesFromObjCFqName -> {
|
||||
objCAnnotations.add(annotation)
|
||||
break
|
||||
}
|
||||
|
||||
refinesInSwiftFqName -> {
|
||||
swiftAnnotations.add(annotation)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return objCAnnotations to swiftAnnotations
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.resolve.konan.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
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.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.konan.diagnostics.NativeObjCRefinementChecker.hidesFromObjCFqName
|
||||
import org.jetbrains.kotlin.resolve.konan.diagnostics.NativeObjCRefinementChecker.refinesInSwiftFqName
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
|
||||
object NativeObjCRefinementOverridesChecker : DeclarationChecker {
|
||||
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (descriptor !is ClassDescriptor) return
|
||||
descriptor.defaultType.memberScope
|
||||
.getContributedDescriptors(DescriptorKindFilter.ALL, MemberScope.Companion.ALL_NAME_FILTER)
|
||||
.forEach {
|
||||
if (it !is CallableMemberDescriptor || it.kind.isReal) return@forEach
|
||||
check(declaration, it, context, emptyList(), emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
fun check(
|
||||
declarationToReport: KtDeclaration,
|
||||
descriptor: CallableMemberDescriptor,
|
||||
context: DeclarationCheckerContext,
|
||||
objCAnnotations: List<AnnotationDescriptor>,
|
||||
swiftAnnotations: List<AnnotationDescriptor>
|
||||
) {
|
||||
if (descriptor.overriddenDescriptors.isEmpty()) return
|
||||
var isHiddenFromObjC = objCAnnotations.isNotEmpty()
|
||||
var isRefinedInSwift = swiftAnnotations.isNotEmpty()
|
||||
val supersNotHiddenFromObjC = mutableListOf<CallableMemberDescriptor>()
|
||||
val supersNotRefinedInSwift = mutableListOf<CallableMemberDescriptor>()
|
||||
for (overriddenDescriptor in descriptor.overriddenDescriptors) {
|
||||
val (superIsHiddenFromObjC, superIsRefinedInSwift) = overriddenDescriptor.inheritsRefinedAnnotations()
|
||||
if (superIsHiddenFromObjC) isHiddenFromObjC = true else supersNotHiddenFromObjC.add(overriddenDescriptor)
|
||||
if (superIsRefinedInSwift) isRefinedInSwift = true else supersNotRefinedInSwift.add(overriddenDescriptor)
|
||||
}
|
||||
if (isHiddenFromObjC && supersNotHiddenFromObjC.isNotEmpty()) {
|
||||
context.trace.reportIncompatibleOverride(declarationToReport, descriptor, objCAnnotations, supersNotHiddenFromObjC)
|
||||
}
|
||||
if (isRefinedInSwift && supersNotRefinedInSwift.isNotEmpty()) {
|
||||
context.trace.reportIncompatibleOverride(declarationToReport, descriptor, swiftAnnotations, supersNotRefinedInSwift)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.inheritsRefinedAnnotations(): Pair<Boolean, Boolean> {
|
||||
val (hasObjC, hasSwift) = hasRefinedAnnotations()
|
||||
if (hasObjC && hasSwift) return true to true
|
||||
if (overriddenDescriptors.isEmpty()) return hasObjC to hasSwift
|
||||
// Note: `checkOverrides` requires all overridden descriptors to be either refined or not refined.
|
||||
val (inheritsObjC, inheritsSwift) = overriddenDescriptors.first().inheritsRefinedAnnotations()
|
||||
return (hasObjC || inheritsObjC) to (hasSwift || inheritsSwift)
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.hasRefinedAnnotations(): Pair<Boolean, Boolean> {
|
||||
var hasObjC = false
|
||||
var hasSwift = false
|
||||
for (annotation in annotations) {
|
||||
val annotations = annotation.annotationClass?.annotations ?: continue
|
||||
for (metaAnnotation in annotations) {
|
||||
when (metaAnnotation.fqName) {
|
||||
hidesFromObjCFqName -> {
|
||||
hasObjC = true
|
||||
break
|
||||
}
|
||||
|
||||
refinesInSwiftFqName -> {
|
||||
hasSwift = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasObjC && hasSwift) return true to true
|
||||
}
|
||||
return hasObjC to hasSwift
|
||||
}
|
||||
|
||||
private fun BindingTrace.reportIncompatibleOverride(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: CallableMemberDescriptor,
|
||||
annotations: List<AnnotationDescriptor>,
|
||||
notRefinedSupers: List<CallableMemberDescriptor>
|
||||
) {
|
||||
val containingDeclarations = notRefinedSupers.map { it.containingDeclaration }
|
||||
if (annotations.isEmpty()) {
|
||||
report(ErrorsNative.INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE.on(declaration, descriptor, containingDeclarations))
|
||||
} else {
|
||||
annotations.forEach {
|
||||
val reportLocation = DescriptorToSourceUtils.getSourceFromAnnotation(it) ?: declaration
|
||||
report(ErrorsNative.INCOMPATIBLE_OBJC_REFINEMENT_OVERRIDE.on(reportLocation, descriptor, containingDeclarations))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.konan.platform
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.useImpl
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
@@ -13,7 +12,6 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.TypeOfChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.inline.ReasonableInlineRule
|
||||
import org.jetbrains.kotlin.resolve.jvm.checkers.SuperCallWithDefaultArgumentsChecker
|
||||
@@ -26,7 +24,8 @@ object NativePlatformConfigurator : PlatformConfiguratorBase(
|
||||
additionalDeclarationCheckers = listOf(
|
||||
NativeThrowsChecker, NativeSharedImmutableChecker,
|
||||
NativeTopLevelSingletonChecker, NativeThreadLocalChecker,
|
||||
NativeObjCNameChecker
|
||||
NativeObjCNameChecker, NativeObjCRefinementChecker,
|
||||
NativeObjCRefinementAnnotationChecker, NativeObjCRefinementOverridesChecker
|
||||
)
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
|
||||
Reference in New Issue
Block a user