[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");
|
runTest("compiler/testData/diagnostics/nativeTests/objCName.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("objCRefinement.kt")
|
||||||
|
public void testObjCRefinement() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/nativeTests/objCRefinement.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("sharedImmutable.kt")
|
@TestMetadata("sharedImmutable.kt")
|
||||||
public void testSharedImmutable() throws Exception {
|
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.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.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.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)
|
val MISSING_EXACT_OBJC_NAME = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
|
||||||
@JvmField
|
@JvmField
|
||||||
val NON_LITERAL_OBJC_NAME_ARG = DiagnosticFactory0.create<KtElement>(Severity.ERROR)
|
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 {
|
init {
|
||||||
Errors.Initializer.initializeFactoryNames(ErrorsNative::class.java)
|
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
|
package org.jetbrains.kotlin.resolve.konan.platform
|
||||||
|
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
|
||||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||||
import org.jetbrains.kotlin.container.useImpl
|
import org.jetbrains.kotlin.container.useImpl
|
||||||
import org.jetbrains.kotlin.container.useInstance
|
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.psi.KtCallableDeclaration
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase
|
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.checkers.ExpectedActualDeclarationChecker
|
||||||
import org.jetbrains.kotlin.resolve.inline.ReasonableInlineRule
|
import org.jetbrains.kotlin.resolve.inline.ReasonableInlineRule
|
||||||
import org.jetbrains.kotlin.resolve.jvm.checkers.SuperCallWithDefaultArgumentsChecker
|
import org.jetbrains.kotlin.resolve.jvm.checkers.SuperCallWithDefaultArgumentsChecker
|
||||||
@@ -26,7 +24,8 @@ object NativePlatformConfigurator : PlatformConfiguratorBase(
|
|||||||
additionalDeclarationCheckers = listOf(
|
additionalDeclarationCheckers = listOf(
|
||||||
NativeThrowsChecker, NativeSharedImmutableChecker,
|
NativeThrowsChecker, NativeSharedImmutableChecker,
|
||||||
NativeTopLevelSingletonChecker, NativeThreadLocalChecker,
|
NativeTopLevelSingletonChecker, NativeThreadLocalChecker,
|
||||||
NativeObjCNameChecker
|
NativeObjCNameChecker, NativeObjCRefinementChecker,
|
||||||
|
NativeObjCRefinementAnnotationChecker, NativeObjCRefinementOverridesChecker
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||||
|
|||||||
Reference in New Issue
Block a user