Load default values for annotation members from classfiles
so that defaults are available to synthetic implementations. #KT-48181 Fixed Implementation is for JVM IR; other backends & FIR need to be supported separately.
This commit is contained in:
+42
-6
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantL
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
|
||||
abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
storageManager: StorageManager,
|
||||
@@ -48,6 +47,12 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
|
||||
protected abstract fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): A
|
||||
|
||||
protected abstract fun loadAnnotationMethodDefaultValue(
|
||||
annotationClass: KotlinJvmBinaryClass,
|
||||
methodSignature: MemberSignature,
|
||||
visitResult: (C) -> Unit
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor?
|
||||
|
||||
private fun loadAnnotationIfNotSpecial(
|
||||
annotationClassId: ClassId,
|
||||
source: SourceElement,
|
||||
@@ -210,7 +215,30 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
return proto.getExtension(JvmProtoBuf.typeParameterAnnotation).map { loadTypeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
override fun loadAnnotationDefaultValue(
|
||||
container: ProtoContainer,
|
||||
proto: ProtoBuf.Property,
|
||||
expectedType: KotlinType
|
||||
): C? {
|
||||
return loadConstantFromProperty(
|
||||
container,
|
||||
proto,
|
||||
AnnotatedCallableKind.PROPERTY_GETTER,
|
||||
expectedType
|
||||
) { annotationParametersDefaultValues[it] }
|
||||
}
|
||||
|
||||
override fun loadPropertyConstant(container: ProtoContainer, proto: ProtoBuf.Property, expectedType: KotlinType): C? {
|
||||
return loadConstantFromProperty(container, proto, AnnotatedCallableKind.PROPERTY, expectedType) { propertyConstants[it] }
|
||||
}
|
||||
|
||||
private fun loadConstantFromProperty(
|
||||
container: ProtoContainer,
|
||||
proto: ProtoBuf.Property,
|
||||
annotatedCallableKind: AnnotatedCallableKind,
|
||||
expectedType: KotlinType,
|
||||
loader: Storage<A, C>.(MemberSignature) -> C?
|
||||
): C? {
|
||||
val specialCase = getSpecialCaseContainerClass(
|
||||
container,
|
||||
property = true,
|
||||
@@ -225,11 +253,11 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
)
|
||||
val signature =
|
||||
getCallableSignature(
|
||||
proto, container.nameResolver, container.typeTable, AnnotatedCallableKind.PROPERTY, requireHasFieldFlag
|
||||
proto, container.nameResolver, container.typeTable, annotatedCallableKind, requireHasFieldFlag
|
||||
) ?: return null
|
||||
|
||||
val constant = storage(kotlinClass).propertyConstants[signature] ?: return null
|
||||
return if (UnsignedTypes.isUnsignedType(expectedType)) transformToUnsignedConstant(constant) else constant
|
||||
val result = storage(kotlinClass).loader(signature) ?: return null
|
||||
return if (UnsignedTypes.isUnsignedType(expectedType)) transformToUnsignedConstant(result) else result
|
||||
}
|
||||
|
||||
private fun findClassWithAnnotationsAndInitializers(
|
||||
@@ -291,6 +319,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
private fun loadAnnotationsAndInitializers(kotlinClass: KotlinJvmBinaryClass): Storage<A, C> {
|
||||
val memberAnnotations = HashMap<MemberSignature, MutableList<A>>()
|
||||
val propertyConstants = HashMap<MemberSignature, C>()
|
||||
val annotationParametersDefaultValues = HashMap<MemberSignature, C>()
|
||||
|
||||
kotlinClass.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor {
|
||||
override fun visitMethod(name: Name, desc: String): KotlinJvmBinaryClass.MethodAnnotationVisitor? {
|
||||
@@ -323,6 +352,12 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
}
|
||||
return loadAnnotationIfNotSpecial(classId, source, result)
|
||||
}
|
||||
|
||||
override fun visitAnnotationMemberDefaultValue(): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
return loadAnnotationMethodDefaultValue(kotlinClass, signature) {
|
||||
annotationParametersDefaultValues[signature] = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open inner class MemberAnnotationVisitor(protected val signature: MemberSignature) : KotlinJvmBinaryClass.AnnotationVisitor {
|
||||
@@ -340,7 +375,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
}
|
||||
}, getCachedFileContent(kotlinClass))
|
||||
|
||||
return Storage(memberAnnotations, propertyConstants)
|
||||
return Storage(memberAnnotations, propertyConstants, annotationParametersDefaultValues)
|
||||
}
|
||||
|
||||
private fun getPropertySignature(
|
||||
@@ -415,6 +450,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||
|
||||
private class Storage<out A, out C>(
|
||||
val memberAnnotations: Map<MemberSignature, List<A>>,
|
||||
val propertyConstants: Map<MemberSignature, C>
|
||||
val propertyConstants: Map<MemberSignature, C>,
|
||||
val annotationParametersDefaultValues: Map<MemberSignature, C>
|
||||
)
|
||||
}
|
||||
|
||||
+130
-66
@@ -14,9 +14,13 @@ import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.compact
|
||||
|
||||
class BinaryClassAnnotationAndConstantLoaderImpl(
|
||||
@@ -66,73 +70,24 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
val annotationClass = resolveClass(annotationClassId)
|
||||
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
||||
return object : AbstractAnnotationArgumentVisitor() {
|
||||
private val arguments = HashMap<Name, ConstantValue<*>>()
|
||||
|
||||
override fun visit(name: Name?, value: Any?) {
|
||||
if (name != null) {
|
||||
arguments[name] = createConstant(name, value)
|
||||
}
|
||||
override fun visitConstantValue(name: Name?, value: ConstantValue<*>) {
|
||||
if (name != null) arguments[name] = value
|
||||
}
|
||||
|
||||
override fun visitClassLiteral(name: Name, value: ClassLiteralValue) {
|
||||
arguments[name] = KClassValue(value)
|
||||
}
|
||||
|
||||
override fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name) {
|
||||
arguments[name] = EnumValue(enumClassId, enumEntryName)
|
||||
}
|
||||
|
||||
override fun visitArray(name: Name): AnnotationArrayArgumentVisitor? {
|
||||
return object : AnnotationArrayArgumentVisitor {
|
||||
private val elements = ArrayList<ConstantValue<*>>()
|
||||
|
||||
override fun visit(value: Any?) {
|
||||
elements.add(createConstant(name, value))
|
||||
}
|
||||
|
||||
override fun visitEnum(enumClassId: ClassId, enumEntryName: Name) {
|
||||
elements.add(EnumValue(enumClassId, enumEntryName))
|
||||
}
|
||||
|
||||
override fun visitClassLiteral(value: ClassLiteralValue) {
|
||||
elements.add(KClassValue(value))
|
||||
}
|
||||
|
||||
override fun visitAnnotation(classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
val list = ArrayList<AnnotationDescriptor>()
|
||||
val visitor = loadAnnotation(classId, SourceElement.NO_SOURCE, list)!!
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
||||
override fun visitEnd() {
|
||||
visitor.visitEnd()
|
||||
elements.add(AnnotationValue(list.single()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass)
|
||||
if (parameter != null) {
|
||||
arguments[name] = ConstantValueFactory.createArrayValue(elements.compact(), parameter.type)
|
||||
} else if (isImplicitRepeatableContainer(annotationClassId) && name.asString() == "value") {
|
||||
// In case this is an implicit repeatable annotation container, its class descriptor can't be resolved by the
|
||||
// frontend, so we'd like to flatten its value and add repeated annotations to the list.
|
||||
// E.g. if we see `@Foo.Container(@Foo(1), @Foo(2))` in the bytecode on some declaration where `Foo` is some
|
||||
// Kotlin-repeatable annotation, we want to read annotations on that declaration as a list `[@Foo(1), @Foo(2)]`.
|
||||
elements.filterIsInstance<AnnotationValue>().mapTo(result, AnnotationValue::value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnnotation(name: Name, classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
val list = ArrayList<AnnotationDescriptor>()
|
||||
val visitor = loadAnnotation(classId, SourceElement.NO_SOURCE, list)!!
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
||||
override fun visitEnd() {
|
||||
visitor.visitEnd()
|
||||
arguments[name] = AnnotationValue(list.single())
|
||||
}
|
||||
override fun visitArrayValue(name: Name?, elements: ArrayList<ConstantValue<*>>) {
|
||||
if (name == null) return
|
||||
val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass)
|
||||
if (parameter != null) {
|
||||
arguments[name] = ConstantValueFactory.createArrayValue(elements.compact(), parameter.type)
|
||||
} else if (isImplicitRepeatableContainer(annotationClassId) && name.asString() == "value") {
|
||||
// In case this is an implicit repeatable annotation container, its class descriptor can't be resolved by the
|
||||
// frontend, so we'd like to flatten its value and add repeated annotations to the list.
|
||||
// E.g. if we see `@Foo.Container(@Foo(1), @Foo(2))` in the bytecode on some declaration where `Foo` is some
|
||||
// Kotlin-repeatable annotation, we want to read annotations on that declaration as a list `[@Foo(1), @Foo(2)]`.
|
||||
elements.filterIsInstance<AnnotationValue>().mapTo(result, AnnotationValue::value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,14 +103,123 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
||||
|
||||
result.add(AnnotationDescriptorImpl(annotationClass.defaultType, arguments, source))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createConstant(name: Name?, value: Any?): ConstantValue<*> {
|
||||
return ConstantValueFactory.createConstantValue(value)
|
||||
?: ErrorValue.create("Unsupported annotation argument: $name")
|
||||
override fun loadAnnotationMethodDefaultValue(
|
||||
annotationClass: KotlinJvmBinaryClass,
|
||||
methodSignature: MemberSignature,
|
||||
visitResult: (ConstantValue<*>) -> Unit
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
return object : AbstractAnnotationArgumentVisitor() {
|
||||
private var defaultValue: ConstantValue<*>? = null
|
||||
|
||||
override fun visitConstantValue(name: Name?, value: ConstantValue<*>) {
|
||||
defaultValue = value
|
||||
}
|
||||
|
||||
override fun visitArrayValue(name: Name?, elements: ArrayList<ConstantValue<*>>) {
|
||||
defaultValue = ArrayValue(elements.compact()) { moduleDescriptor ->
|
||||
guessArrayType(moduleDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
defaultValue?.let(visitResult)
|
||||
}
|
||||
|
||||
private fun guessArrayType(
|
||||
moduleDescriptor: ModuleDescriptor
|
||||
): KotlinType {
|
||||
val elementDesc = methodSignature.signature.substringAfterLast(')').removePrefix("[")
|
||||
// Some fast-path guesses
|
||||
JvmPrimitiveType.getByDesc(elementDesc)
|
||||
?.let { return moduleDescriptor.builtIns.getPrimitiveArrayKotlinType(it.primitiveType) }
|
||||
if (elementDesc == "Ljava/lang/String;") return moduleDescriptor.builtIns.getArrayType(
|
||||
Variance.INVARIANT,
|
||||
moduleDescriptor.builtIns.stringType
|
||||
)
|
||||
// Slow path resolving @JvmName
|
||||
val propertiesNames = moduleDescriptor.findNonGenericClassAcrossDependencies(annotationClass.classId, notFoundClasses)
|
||||
.unsubstitutedMemberScope.getContributedDescriptors().filterIsInstance<PropertyDescriptor>()
|
||||
.filter { prop ->
|
||||
val name = prop.getter?.let { DescriptorUtils.getJvmName(it) ?: prop.name.asString() }
|
||||
name == methodSignature.signature.substringBefore('(')
|
||||
}
|
||||
val requiredProp = propertiesNames.singleOrNull()
|
||||
?: error("Signature ${methodSignature.signature} does not belong to class ${annotationClass.classId} or multiple duplicates found")
|
||||
return requiredProp.type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private abstract inner class AbstractAnnotationArgumentVisitor : KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
||||
abstract fun visitConstantValue(name: Name?, value: ConstantValue<*>)
|
||||
abstract override fun visitEnd()
|
||||
abstract fun visitArrayValue(name: Name?, elements: ArrayList<ConstantValue<*>>)
|
||||
|
||||
override fun visit(name: Name?, value: Any?) {
|
||||
visitConstantValue(name, createConstant(name, value))
|
||||
}
|
||||
|
||||
override fun visitClassLiteral(name: Name?, value: ClassLiteralValue) {
|
||||
visitConstantValue(name, KClassValue(value))
|
||||
}
|
||||
|
||||
override fun visitEnum(name: Name?, enumClassId: ClassId, enumEntryName: Name) {
|
||||
visitConstantValue(name, EnumValue(enumClassId, enumEntryName))
|
||||
}
|
||||
|
||||
override fun visitArray(name: Name?): AnnotationArrayArgumentVisitor? {
|
||||
return object : AnnotationArrayArgumentVisitor {
|
||||
private val elements = ArrayList<ConstantValue<*>>()
|
||||
|
||||
override fun visit(value: Any?) {
|
||||
elements.add(createConstant(name, value))
|
||||
}
|
||||
|
||||
override fun visitEnum(enumClassId: ClassId, enumEntryName: Name) {
|
||||
elements.add(EnumValue(enumClassId, enumEntryName))
|
||||
}
|
||||
|
||||
override fun visitClassLiteral(value: ClassLiteralValue) {
|
||||
elements.add(KClassValue(value))
|
||||
}
|
||||
|
||||
override fun visitAnnotation(classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
val list = ArrayList<AnnotationDescriptor>()
|
||||
val visitor = loadAnnotation(classId, SourceElement.NO_SOURCE, list)!!
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
||||
override fun visitEnd() {
|
||||
visitor.visitEnd()
|
||||
elements.add(AnnotationValue(list.single()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
visitArrayValue(name, elements)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnnotation(name: Name?, classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
val list = ArrayList<AnnotationDescriptor>()
|
||||
val visitor = loadAnnotation(classId, SourceElement.NO_SOURCE, list)!!
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
||||
override fun visitEnd() {
|
||||
visitor.visitEnd()
|
||||
visitConstantValue(name, AnnotationValue(list.single()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createConstant(name: Name?, value: Any?): ConstantValue<*> {
|
||||
return ConstantValueFactory.createConstantValue(value)
|
||||
?: ErrorValue.create("Unsupported annotation argument: $name")
|
||||
}
|
||||
|
||||
private fun resolveClass(classId: ClassId): ClassDescriptor {
|
||||
return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses)
|
||||
}
|
||||
|
||||
+15
-15
@@ -168,13 +168,13 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassLiteral(@NotNull Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
||||
public void visitClassLiteral(@Nullable Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
|
||||
String string = name.asString();
|
||||
public AnnotationArrayArgumentVisitor visitArray(@Nullable Name name) {
|
||||
String string = name != null ? name.asString() : null;
|
||||
if (METADATA_DATA_FIELD_NAME.equals(string)) {
|
||||
return dataArrayVisitor();
|
||||
}
|
||||
@@ -207,12 +207,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
public void visitEnum(@Nullable Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AnnotationArgumentVisitor visitAnnotation(@NotNull Name name, @NotNull ClassId classId) {
|
||||
public AnnotationArgumentVisitor visitAnnotation(@Nullable Name name, @NotNull ClassId classId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -238,13 +238,13 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassLiteral(@NotNull Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
||||
public void visitClassLiteral(@Nullable Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
|
||||
String string = name.asString();
|
||||
public AnnotationArrayArgumentVisitor visitArray(@Nullable Name name) {
|
||||
String string = name != null ? name.asString() : null;
|
||||
if ("data".equals(string) || "filePartClassNames".equals(string)) {
|
||||
return dataArrayVisitor();
|
||||
}
|
||||
@@ -277,12 +277,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
public void visitEnum(@Nullable Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AnnotationArgumentVisitor visitAnnotation(@NotNull Name name, @NotNull ClassId classId) {
|
||||
public AnnotationArgumentVisitor visitAnnotation(@Nullable Name name, @NotNull ClassId classId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -297,13 +297,13 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassLiteral(@NotNull Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
||||
public void visitClassLiteral(@Nullable Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
|
||||
String string = name.asString();
|
||||
public AnnotationArrayArgumentVisitor visitArray(@Nullable Name name) {
|
||||
String string = name != null ? name.asString() : null;
|
||||
if (SERIALIZED_IR_BYTES_FIELD_NAME.equals(string)) {
|
||||
return serializedIrArrayVisitor();
|
||||
}
|
||||
@@ -323,12 +323,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
public void visitEnum(@Nullable Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AnnotationArgumentVisitor visitAnnotation(@NotNull Name name, @NotNull ClassId classId) {
|
||||
public AnnotationArgumentVisitor visitAnnotation(@Nullable Name name, @NotNull ClassId classId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -44,18 +44,20 @@ interface KotlinJvmBinaryClass {
|
||||
|
||||
interface MethodAnnotationVisitor : AnnotationVisitor {
|
||||
fun visitParameterAnnotation(index: Int, classId: ClassId, source: SourceElement): AnnotationArgumentVisitor?
|
||||
|
||||
fun visitAnnotationMemberDefaultValue(): AnnotationArgumentVisitor?
|
||||
}
|
||||
|
||||
interface AnnotationArgumentVisitor {
|
||||
fun visit(name: Name?, value: Any?)
|
||||
|
||||
fun visitClassLiteral(name: Name, value: ClassLiteralValue)
|
||||
fun visitClassLiteral(name: Name?, value: ClassLiteralValue)
|
||||
|
||||
fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name)
|
||||
fun visitEnum(name: Name?, enumClassId: ClassId, enumEntryName: Name)
|
||||
|
||||
fun visitAnnotation(name: Name, classId: ClassId): AnnotationArgumentVisitor?
|
||||
fun visitAnnotation(name: Name?, classId: ClassId): AnnotationArgumentVisitor?
|
||||
|
||||
fun visitArray(name: Name): AnnotationArrayArgumentVisitor?
|
||||
fun visitArray(name: Name?): AnnotationArrayArgumentVisitor?
|
||||
|
||||
fun visitEnd()
|
||||
}
|
||||
|
||||
+6
@@ -78,4 +78,10 @@ interface AnnotationAndConstantLoader<out A : Any, out C : Any> {
|
||||
proto: ProtoBuf.Property,
|
||||
expectedType: KotlinType
|
||||
): C?
|
||||
|
||||
fun loadAnnotationDefaultValue(
|
||||
container: ProtoContainer,
|
||||
proto: ProtoBuf.Property,
|
||||
expectedType: KotlinType
|
||||
): C?
|
||||
}
|
||||
|
||||
+9
@@ -104,4 +104,13 @@ class AnnotationAndConstantLoaderImpl(
|
||||
val value = proto.getExtensionOrNull(protocol.compileTimeValue) ?: return null
|
||||
return deserializer.resolveValue(expectedType, value, container.nameResolver)
|
||||
}
|
||||
|
||||
override fun loadAnnotationDefaultValue(
|
||||
container: ProtoContainer,
|
||||
proto: ProtoBuf.Property,
|
||||
expectedType: KotlinType
|
||||
): ConstantValue<*>? {
|
||||
// Implement this method to properly support Annotations Instantiation feature
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -140,6 +140,15 @@ class MemberDeserializer(private val c: DeserializationContext) {
|
||||
)
|
||||
}
|
||||
|
||||
if ((c.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.ANNOTATION_CLASS) {
|
||||
property.setCompileTimeInitializer(
|
||||
c.storageManager.createNullableLazyValue {
|
||||
val container = c.containingDeclaration.asProtoContainer()!!
|
||||
c.components.annotationAndConstantLoader.loadAnnotationDefaultValue(container, proto, property.returnType)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
property.initialize(
|
||||
getter, setter,
|
||||
FieldDescriptorImpl(getPropertyFieldAnnotations(proto, isDelegate = false), property),
|
||||
|
||||
Reference in New Issue
Block a user