From b1a28bcc6a594e1b6b687f41fb5abc829e9a450b Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Thu, 16 Jul 2015 18:01:22 +0300 Subject: [PATCH] Support @get and @set annotations --- .../kotlin/codegen/FunctionCodegen.java | 25 ++++++++++++++++++- .../jetbrains/kotlin/diagnostics/Errors.java | 3 +++ .../rendering/DefaultErrorMessages.java | 3 +++ .../kotlin/psi/JetAnnotationUseSiteTarget.kt | 2 ++ .../kotlin/resolve/ModifiersChecker.java | 21 ++++++++++++++++ .../annotations/AnnotationUseSiteTarget.kt | 10 +++++--- 6 files changed, 59 insertions(+), 5 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 027fa80e720..4abd93ab720 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -34,7 +34,10 @@ import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor; 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.Annotated; +import org.jetbrains.kotlin.descriptors.annotations.AnnotatedWithAdditionalAnnotations; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget; import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo; import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeDeclarationsPackage; import org.jetbrains.kotlin.name.FqName; @@ -71,6 +74,7 @@ import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny; import static org.jetbrains.kotlin.codegen.AsmUtil.*; import static org.jetbrains.kotlin.codegen.JvmSerializationBindings.*; import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION; +import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*; import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE; @@ -166,7 +170,8 @@ public class FunctionCodegen { v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod); } - AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, asmMethod.getReturnType()); + generateTargetedAnnotations(functionDescriptor, asmMethod, mv); + generateParameterAnnotations(functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor)); generateBridges(functionDescriptor); @@ -210,6 +215,24 @@ public class FunctionCodegen { methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext); } + private void generateTargetedAnnotations( + @NotNull FunctionDescriptor functionDescriptor, + Method asmMethod, + MethodVisitor mv + ) { + AnnotationCodegen annotationCodegen = AnnotationCodegen.forMethod(mv, typeMapper); + + if (functionDescriptor instanceof PropertyAccessorDescriptor) { + AnnotationUseSiteTarget target = functionDescriptor instanceof PropertySetterDescriptor ? PROPERTY_SETTER : PROPERTY_GETTER; + Annotated annotated = new AnnotatedWithAdditionalAnnotations( + null, ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty()); + + annotationCodegen.genAnnotations(annotated, asmMethod.getReturnType(), target); + } + + annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType()); + } + private void generateParameterAnnotations( @NotNull FunctionDescriptor functionDescriptor, @NotNull MethodVisitor mv, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 6d9dc527708..cfffb43e7b4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -133,6 +133,9 @@ public interface Errors { DiagnosticFactory0 INAPPLICABLE_FIELD_TARGET = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD = 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); // Classes and traits 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 657f957e039..af9e61bbdf0 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,9 @@ 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_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"); MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING); MAP.put(ABSTRACT_MODIFIER_IN_TRAIT, "Modifier ''abstract'' is redundant in interface"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationUseSiteTarget.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationUseSiteTarget.kt index 4313db846f1..15a9577b459 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationUseSiteTarget.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetAnnotationUseSiteTarget.kt @@ -38,6 +38,8 @@ public class JetAnnotationUseSiteTarget : JetElementImplStub AnnotationUseSiteTarget.FIELD JetTokens.FILE_KEYWORD -> AnnotationUseSiteTarget.FILE + 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 035e661d17c..7d8025df84f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.java @@ -234,6 +234,27 @@ public class ModifiersChecker { break; case FILE: throw new IllegalArgumentException("@file annotations are not allowed here"); + case PROPERTY_GETTER: + reportIfNotPropertyDescriptor(descriptor, annotation, INAPPLICABLE_GET_TARGET); + break; + case PROPERTY_SETTER: { + reportIfNotMutableProperty(descriptor, annotation, INAPPLICABLE_SET_TARGET); + break; + } + } + } + } + + private void reportIfNotMutableProperty( + DeclarationDescriptor descriptor, + AnnotationDescriptor annotation, + DiagnosticFactory0 diagnosticFactory + ) { + reportIfNotPropertyDescriptor(descriptor, annotation, diagnosticFactory); + + if (descriptor instanceof PropertyDescriptor) { + if (!((PropertyDescriptor) descriptor).isVar()) { + reportAnnotationTargetNotApplicable(annotation, INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE); } } } 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 f35796bd649..c951c0424f5 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationUseSiteTarget.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/annotations/AnnotationUseSiteTarget.kt @@ -16,9 +16,11 @@ package org.jetbrains.kotlin.descriptors.annotations -public enum class AnnotationUseSiteTarget() { - FIELD, - FILE; +public enum class AnnotationUseSiteTarget(renderName: String? = null) { + FIELD(), + FILE(), + PROPERTY_GETTER("get"), + PROPERTY_SETTER("set"); - public val renderName: String = name().toLowerCase() + public val renderName: String = renderName ?: name().toLowerCase() } \ No newline at end of file