Support @property annotations
This commit is contained in:
@@ -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<AnnotationDescriptor> 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();
|
||||
|
||||
@@ -133,6 +133,7 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_PROPERTY_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_GET_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_SET_TARGET = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
+1
@@ -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");
|
||||
|
||||
@@ -38,6 +38,7 @@ public class JetAnnotationUseSiteTarget : JetElementImplStub<KotlinPlaceHolderSt
|
||||
return when (node.getElementType()) {
|
||||
JetTokens.FIELD_KEYWORD -> 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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
+1
@@ -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");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user