Support @get and @set annotations
This commit is contained in:
@@ -34,7 +34,10 @@ import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor;
|
|||||||
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.Annotated;
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotatedWithAdditionalAnnotations;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||||
import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
|
import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
|
||||||
import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeDeclarationsPackage;
|
import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeDeclarationsPackage;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
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.AsmUtil.*;
|
||||||
import static org.jetbrains.kotlin.codegen.JvmSerializationBindings.*;
|
import static org.jetbrains.kotlin.codegen.JvmSerializationBindings.*;
|
||||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
|
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.DescriptorToSourceUtils.getSourceFromDescriptor;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
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);
|
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));
|
generateParameterAnnotations(functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor));
|
||||||
|
|
||||||
generateBridges(functionDescriptor);
|
generateBridges(functionDescriptor);
|
||||||
@@ -210,6 +215,24 @@ public class FunctionCodegen {
|
|||||||
methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
|
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(
|
private void generateParameterAnnotations(
|
||||||
@NotNull FunctionDescriptor functionDescriptor,
|
@NotNull FunctionDescriptor functionDescriptor,
|
||||||
@NotNull MethodVisitor mv,
|
@NotNull MethodVisitor mv,
|
||||||
|
|||||||
@@ -133,6 +133,9 @@ 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_GET_TARGET = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory0<PsiElement> INAPPLICABLE_SET_TARGET = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory0<PsiElement> INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE = DiagnosticFactory0.create(ERROR);
|
||||||
|
|
||||||
// Classes and traits
|
// Classes and traits
|
||||||
|
|
||||||
|
|||||||
+3
@@ -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, "''@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_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(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");
|
MAP.put(ABSTRACT_MODIFIER_IN_TRAIT, "Modifier ''abstract'' is redundant in interface");
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ 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.GET_KEYWORD -> AnnotationUseSiteTarget.PROPERTY_GETTER
|
||||||
|
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,27 @@ 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_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<PsiElement> diagnosticFactory
|
||||||
|
) {
|
||||||
|
reportIfNotPropertyDescriptor(descriptor, annotation, diagnosticFactory);
|
||||||
|
|
||||||
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
|
if (!((PropertyDescriptor) descriptor).isVar()) {
|
||||||
|
reportAnnotationTargetNotApplicable(annotation, INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-4
@@ -16,9 +16,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.descriptors.annotations
|
package org.jetbrains.kotlin.descriptors.annotations
|
||||||
|
|
||||||
public enum class AnnotationUseSiteTarget() {
|
public enum class AnnotationUseSiteTarget(renderName: String? = null) {
|
||||||
FIELD,
|
FIELD(),
|
||||||
FILE;
|
FILE(),
|
||||||
|
PROPERTY_GETTER("get"),
|
||||||
|
PROPERTY_SETTER("set");
|
||||||
|
|
||||||
public val renderName: String = name().toLowerCase()
|
public val renderName: String = renderName ?: name().toLowerCase()
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user