diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index fce234055e0..c406b0dd2f7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.context.*; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.psi.*; @@ -110,8 +111,12 @@ public class PropertyCodegen { } else { assert declaration != null : "Declaration is null for different context: " + context; - if (!generateBackingField(declaration, descriptor)) { - generateSyntheticMethodIfNeeded(descriptor); + + List propertyTargetedAnnotations = + descriptor.getAnnotations().getUseSiteTargetedAnnotations(AnnotationUseSiteTarget.PROPERTY); + + if (!generateBackingField(declaration, descriptor) || !propertyTargetedAnnotations.isEmpty()) { + generateSyntheticMethodIfNeeded(descriptor, !propertyTargetedAnnotations.isEmpty()); } } @@ -210,8 +215,8 @@ public class PropertyCodegen { // Annotations on properties without backing fields are stored in bytecode on an empty synthetic method. This way they're still // accessible via reflection, and 'deprecated' and 'private' flags prevent this method from being called accidentally - private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor) { - if (descriptor.getAnnotations().isEmpty()) return; + private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, boolean hasPropertyTargetedAnnotations) { + if (descriptor.getAnnotations().isEmpty() && !hasPropertyTargetedAnnotations) return; ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter(); String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName()); @@ -220,7 +225,7 @@ public class PropertyCodegen { if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) { int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC; MethodVisitor mv = v.newMethod(OtherOrigin(descriptor), flags, name, desc, null, null); - AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor, Type.VOID_TYPE); + AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor, Type.VOID_TYPE, AnnotationUseSiteTarget.PROPERTY); mv.visitCode(); mv.visitInsn(Opcodes.RETURN); mv.visitEnd(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index cfffb43e7b4..40af01971d1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -133,6 +133,7 @@ public interface Errors { DiagnosticFactory0 INAPPLICABLE_FIELD_TARGET = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 INAPPLICABLE_PROPERTY_TARGET = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INAPPLICABLE_GET_TARGET = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INAPPLICABLE_SET_TARGET = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index af9e61bbdf0..e052a46a050 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -126,6 +126,7 @@ public class DefaultErrorMessages { MAP.put(INAPPLICABLE_FIELD_TARGET, "''@field:'' annotations could be applied only to property declarations"); MAP.put(INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD, "Property has neither a backing field nor a delegate"); + MAP.put(INAPPLICABLE_PROPERTY_TARGET, "''@property:'' annotations could be applied only to property declarations"); MAP.put(INAPPLICABLE_GET_TARGET, "''@get:'' annotations could be applied only to property declarations"); MAP.put(INAPPLICABLE_SET_TARGET, "''@set:'' annotations could be applied only to property declarations"); MAP.put(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, "Property must be mutable"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationUseSiteTarget.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationUseSiteTarget.kt index 15a9577b459..3973aa3c191 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationUseSiteTarget.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationUseSiteTarget.kt @@ -38,6 +38,7 @@ public class JetAnnotationUseSiteTarget : JetElementImplStub AnnotationUseSiteTarget.FIELD JetTokens.FILE_KEYWORD -> AnnotationUseSiteTarget.FILE + JetTokens.PROPERTY_KEYWORD -> AnnotationUseSiteTarget.PROPERTY JetTokens.GET_KEYWORD -> AnnotationUseSiteTarget.PROPERTY_GETTER JetTokens.SET_KEYWORD -> AnnotationUseSiteTarget.PROPERTY_SETTER else -> throw IllegalStateException("Unknown annotation target " + node.getText()) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java index 7d8025df84f..3cb7c17d5f3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java @@ -234,6 +234,9 @@ public class ModifiersChecker { break; case FILE: throw new IllegalArgumentException("@file annotations are not allowed here"); + case PROPERTY: + reportIfNotPropertyDescriptor(descriptor, annotation, INAPPLICABLE_PROPERTY_TARGET); + break; case PROPERTY_GETTER: reportIfNotPropertyDescriptor(descriptor, annotation, INAPPLICABLE_GET_TARGET); break; diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationUseSiteTarget.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationUseSiteTarget.kt index c951c0424f5..af2fee5f27f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationUseSiteTarget.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationUseSiteTarget.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.descriptors.annotations public enum class AnnotationUseSiteTarget(renderName: String? = null) { FIELD(), FILE(), + PROPERTY(), PROPERTY_GETTER("get"), PROPERTY_SETTER("set");