From a2bba7c8f139b0a50002b466596ea11bb1cfff48 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 15 Jan 2016 15:31:14 +0300 Subject: [PATCH] JvmField forbidden for delegated properties --- .../kotlin/resolve/jvm/annotationUtil.kt | 15 +-------------- .../jvm/checkers/JvmFieldApplicabilityChecker.kt | 5 ++++- .../annotations/jvmField/jvmFieldApplicability.kt | 5 ++++- .../jvmField/jvmFieldApplicability.txt | 1 + 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotationUtil.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotationUtil.kt index 4c762c2dc56..ed16f409b01 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotationUtil.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/annotationUtil.kt @@ -27,20 +27,7 @@ fun DeclarationDescriptor.hasJvmOverloadsAnnotation(): Boolean { return annotations.findAnnotation(FqName("kotlin.jvm.JvmOverloads")) != null } -fun DeclarationDescriptor.findJvmFieldAnnotation(): AnnotationDescriptor? { - val fqName = FqName("kotlin.jvm.JvmField") - val annotation = annotations.findAnnotation(fqName) - if (annotation != null) { - return annotation; - } - - return annotations.getUseSiteTargetedAnnotations().asSequence().filter { - it.target == AnnotationUseSiteTarget.FIELD - }.map { it.annotation }.firstOrNull { - val descriptor = it.type.constructor.declarationDescriptor - descriptor is ClassDescriptor && fqName.toUnsafe() == DescriptorUtils.getFqName(descriptor) - } -} +fun DeclarationDescriptor.findJvmFieldAnnotation() = DescriptorUtils.getAnnotationByFqName(annotations, FqName("kotlin.jvm.JvmField")) fun DeclarationDescriptor.hasJvmFieldAnnotation(): Boolean { return findJvmFieldAnnotation() != null diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmFieldApplicabilityChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmFieldApplicabilityChecker.kt index f0e5c3507df..fdc75dacf10 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmFieldApplicabilityChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JvmFieldApplicabilityChecker.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.isInsideJvmMultifileClassFile import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DeclarationChecker import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils @@ -40,7 +41,8 @@ class JvmFieldApplicabilityChecker : DeclarationChecker { LATEINIT("JvmField cannot be applied to lateinit property"), CONST("JvmField cannot be applied to const property"), INSIDE_COMPANION_OF_INTERFACE("JvmField cannot be applied to a property defined in companion object of interface"), - TOP_LEVEL_PROPERTY_OF_MULTIFILE_FACADE("JvmField cannot be applied to top level property of a file annotated with ${JvmFileClassUtil.JVM_MULTIFILE_CLASS_SHORT}") + TOP_LEVEL_PROPERTY_OF_MULTIFILE_FACADE("JvmField cannot be applied to top level property of a file annotated with ${JvmFileClassUtil.JVM_MULTIFILE_CLASS_SHORT}"), + DELEGATE("JvmField cannot be applied to delegated property") } override fun check( @@ -54,6 +56,7 @@ class JvmFieldApplicabilityChecker : DeclarationChecker { val problem = when { // First two cases just prevent duplication of WRONG_ANNOTATION_TARGET descriptor !is PropertyDescriptor -> return + declaration is KtProperty && declaration.hasDelegate() -> DELEGATE !descriptor.hasBackingField(bindingContext) -> return descriptor.isOverridable -> NOT_FINAL Visibilities.isPrivate(descriptor.visibility) -> PRIVATE diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.kt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.kt index 1edd19c8e59..1fb4e5719bd 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.kt @@ -13,7 +13,7 @@ abstract class C : I{ @kotlin.jvm.JvmField private fun foo(s: String = "OK") { } - @JvmField val a: String by lazy { "A" } + @JvmField val a: String by lazy { "A" } @JvmField open val b: Int = 3 @@ -49,6 +49,9 @@ interface I { class G { @JvmField lateinit var lateInit: String + + @delegate:JvmField + val s: String by lazy { "s" } } @JvmField diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.txt index a493bc6c1ce..35266be3dfa 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/jvmField/jvmFieldApplicability.txt @@ -25,6 +25,7 @@ package public final class G { public constructor G() @kotlin.jvm.JvmField() public final lateinit var lateInit: kotlin.String + @delegate:kotlin.jvm.JvmField() public final val s: kotlin.String 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