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.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
@@ -110,8 +111,12 @@ public class PropertyCodegen {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert declaration != null : "Declaration is null for different context: " + context;
|
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
|
// 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
|
// accessible via reflection, and 'deprecated' and 'private' flags prevent this method from being called accidentally
|
||||||
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor) {
|
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor, boolean hasPropertyTargetedAnnotations) {
|
||||||
if (descriptor.getAnnotations().isEmpty()) return;
|
if (descriptor.getAnnotations().isEmpty() && !hasPropertyTargetedAnnotations) return;
|
||||||
|
|
||||||
ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
|
ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
|
||||||
String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName());
|
String name = JvmAbi.getSyntheticMethodNameForAnnotatedProperty(descriptor.getName());
|
||||||
@@ -220,7 +225,7 @@ public class PropertyCodegen {
|
|||||||
if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) {
|
if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) {
|
||||||
int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
|
int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
|
||||||
MethodVisitor mv = v.newMethod(OtherOrigin(descriptor), flags, name, desc, null, null);
|
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.visitCode();
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ public interface Errors {
|
|||||||
|
|
||||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_FIELD_TARGET_NO_BACKING_FIELD = 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_GET_TARGET = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_SET_TARGET = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> INAPPLICABLE_SET_TARGET = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = 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, "''@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_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_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_SET_TARGET, "''@set:'' annotations could be applied only to property declarations");
|
||||||
MAP.put(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, "Property must be mutable");
|
MAP.put(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, "Property must be mutable");
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public class JetAnnotationUseSiteTarget : JetElementImplStub<KotlinPlaceHolderSt
|
|||||||
return when (node.getElementType()) {
|
return when (node.getElementType()) {
|
||||||
JetTokens.FIELD_KEYWORD -> AnnotationUseSiteTarget.FIELD
|
JetTokens.FIELD_KEYWORD -> AnnotationUseSiteTarget.FIELD
|
||||||
JetTokens.FILE_KEYWORD -> AnnotationUseSiteTarget.FILE
|
JetTokens.FILE_KEYWORD -> AnnotationUseSiteTarget.FILE
|
||||||
|
JetTokens.PROPERTY_KEYWORD -> AnnotationUseSiteTarget.PROPERTY
|
||||||
JetTokens.GET_KEYWORD -> AnnotationUseSiteTarget.PROPERTY_GETTER
|
JetTokens.GET_KEYWORD -> AnnotationUseSiteTarget.PROPERTY_GETTER
|
||||||
JetTokens.SET_KEYWORD -> AnnotationUseSiteTarget.PROPERTY_SETTER
|
JetTokens.SET_KEYWORD -> AnnotationUseSiteTarget.PROPERTY_SETTER
|
||||||
else -> throw IllegalStateException("Unknown annotation target " + node.getText())
|
else -> throw IllegalStateException("Unknown annotation target " + node.getText())
|
||||||
|
|||||||
@@ -234,6 +234,9 @@ public class ModifiersChecker {
|
|||||||
break;
|
break;
|
||||||
case FILE:
|
case FILE:
|
||||||
throw new IllegalArgumentException("@file annotations are not allowed here");
|
throw new IllegalArgumentException("@file annotations are not allowed here");
|
||||||
|
case PROPERTY:
|
||||||
|
reportIfNotPropertyDescriptor(descriptor, annotation, INAPPLICABLE_PROPERTY_TARGET);
|
||||||
|
break;
|
||||||
case PROPERTY_GETTER:
|
case PROPERTY_GETTER:
|
||||||
reportIfNotPropertyDescriptor(descriptor, annotation, INAPPLICABLE_GET_TARGET);
|
reportIfNotPropertyDescriptor(descriptor, annotation, INAPPLICABLE_GET_TARGET);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+1
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.descriptors.annotations
|
|||||||
public enum class AnnotationUseSiteTarget(renderName: String? = null) {
|
public enum class AnnotationUseSiteTarget(renderName: String? = null) {
|
||||||
FIELD(),
|
FIELD(),
|
||||||
FILE(),
|
FILE(),
|
||||||
|
PROPERTY(),
|
||||||
PROPERTY_GETTER("get"),
|
PROPERTY_GETTER("get"),
|
||||||
PROPERTY_SETTER("set");
|
PROPERTY_SETTER("set");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user