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:
+6
@@ -467,6 +467,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt");
|
runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multimoduleCreation.kt")
|
||||||
|
public void testMultimoduleCreation() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/annotations/instances/multimoduleCreation.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("multimoduleInlining.kt")
|
@TestMetadata("multimoduleInlining.kt")
|
||||||
public void testMultimoduleInlining() throws Exception {
|
public void testMultimoduleInlining() throws Exception {
|
||||||
|
|||||||
+8
-4
@@ -80,17 +80,20 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClassLiteral(name: Name, value: ClassLiteralValue) {
|
override fun visitClassLiteral(name: Name?, value: ClassLiteralValue) {
|
||||||
|
if (name == null) return
|
||||||
argumentMap[name] = buildGetClassCall {
|
argumentMap[name] = buildGetClassCall {
|
||||||
argumentList = buildUnaryArgumentList(value.toFirClassReferenceExpression())
|
argumentList = buildUnaryArgumentList(value.toFirClassReferenceExpression())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name) {
|
override fun visitEnum(name: Name?, enumClassId: ClassId, enumEntryName: Name) {
|
||||||
|
if (name == null) return
|
||||||
argumentMap[name] = enumClassId.toEnumEntryReferenceExpression(enumEntryName)
|
argumentMap[name] = enumClassId.toEnumEntryReferenceExpression(enumEntryName)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitArray(name: Name): KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor {
|
override fun visitArray(name: Name?): KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor? {
|
||||||
|
if (name == null) return null
|
||||||
return object : KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor {
|
return object : KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor {
|
||||||
private val elements = mutableListOf<FirExpression>()
|
private val elements = mutableListOf<FirExpression>()
|
||||||
|
|
||||||
@@ -131,7 +134,8 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitAnnotation(name: Name, classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
override fun visitAnnotation(name: Name?, classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||||
|
if (name == null) return null
|
||||||
val list = mutableListOf<FirAnnotation>()
|
val list = mutableListOf<FirAnnotation>()
|
||||||
val visitor = loadAnnotation(classId, list)
|
val visitor = loadAnnotation(classId, list)
|
||||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
||||||
|
|||||||
+5
@@ -322,6 +322,11 @@ private fun FirSession.loadMemberAnnotations(
|
|||||||
}
|
}
|
||||||
return annotationsLoader.loadAnnotationIfNotSpecial(classId, result)
|
return annotationsLoader.loadAnnotationIfNotSpecial(classId, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitAnnotationMemberDefaultValue(): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||||
|
// TODO: load annotation default values to properly support annotation instantiation feature
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open inner class MemberAnnotationVisitor(protected val signature: MemberSignature) : KotlinJvmBinaryClass.AnnotationVisitor {
|
open inner class MemberAnnotationVisitor(protected val signature: MemberSignature) : KotlinJvmBinaryClass.AnnotationVisitor {
|
||||||
|
|||||||
+13
-5
@@ -173,17 +173,18 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
|
|||||||
return new org.jetbrains.org.objectweb.asm.AnnotationVisitor(API_VERSION) {
|
return new org.jetbrains.org.objectweb.asm.AnnotationVisitor(API_VERSION) {
|
||||||
@Override
|
@Override
|
||||||
public void visit(String name, @NotNull Object value) {
|
public void visit(String name, @NotNull Object value) {
|
||||||
|
Name identifier = name == null ? null : Name.identifier(name);
|
||||||
if (value instanceof Type) {
|
if (value instanceof Type) {
|
||||||
v.visitClassLiteral(Name.identifier(name), resolveKotlinNameByType((Type) value, innerClasses));
|
v.visitClassLiteral(identifier, resolveKotlinNameByType((Type) value, innerClasses));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.visit(name == null ? null : Name.identifier(name), value);
|
v.visit(identifier, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public org.jetbrains.org.objectweb.asm.AnnotationVisitor visitArray(String name) {
|
public org.jetbrains.org.objectweb.asm.AnnotationVisitor visitArray(String name) {
|
||||||
AnnotationArrayArgumentVisitor arv = v.visitArray(Name.identifier(name));
|
AnnotationArrayArgumentVisitor arv = v.visitArray(name == null ? null : Name.identifier(name));
|
||||||
return arv == null ? null : new org.jetbrains.org.objectweb.asm.AnnotationVisitor(API_VERSION) {
|
return arv == null ? null : new org.jetbrains.org.objectweb.asm.AnnotationVisitor(API_VERSION) {
|
||||||
@Override
|
@Override
|
||||||
public void visit(String name, @NotNull Object value) {
|
public void visit(String name, @NotNull Object value) {
|
||||||
@@ -215,13 +216,14 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public org.jetbrains.org.objectweb.asm.AnnotationVisitor visitAnnotation(String name, @NotNull String desc) {
|
public org.jetbrains.org.objectweb.asm.AnnotationVisitor visitAnnotation(String name, @NotNull String desc) {
|
||||||
AnnotationArgumentVisitor arv = v.visitAnnotation(Name.identifier(name), resolveNameByDesc(desc, innerClasses));
|
AnnotationArgumentVisitor arv =
|
||||||
|
v.visitAnnotation(name == null ? null : Name.identifier(name), resolveNameByDesc(desc, innerClasses));
|
||||||
return arv == null ? null : convertAnnotationVisitor(arv, innerClasses);
|
return arv == null ? null : convertAnnotationVisitor(arv, innerClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitEnum(String name, @NotNull String desc, @NotNull String value) {
|
public void visitEnum(String name, @NotNull String desc, @NotNull String value) {
|
||||||
v.visitEnum(Name.identifier(name), resolveNameByDesc(desc, innerClasses), Name.identifier(value));
|
v.visitEnum(name == null ? null : Name.identifier(name), resolveNameByDesc(desc, innerClasses), Name.identifier(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -269,6 +271,12 @@ public abstract class FileBasedKotlinClass implements KotlinJvmBinaryClass {
|
|||||||
return convertAnnotationVisitor(v, desc, innerClasses);
|
return convertAnnotationVisitor(v, desc, innerClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.jetbrains.org.objectweb.asm.AnnotationVisitor visitAnnotationDefault() {
|
||||||
|
AnnotationArgumentVisitor av = v.visitAnnotationMemberDefaultValue();
|
||||||
|
return av == null ? null : convertAnnotationVisitor(av, innerClasses);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public org.jetbrains.org.objectweb.asm.AnnotationVisitor visitParameterAnnotation(int parameter, @NotNull String desc, boolean visible) {
|
public org.jetbrains.org.objectweb.asm.AnnotationVisitor visitParameterAnnotation(int parameter, @NotNull String desc, boolean visible) {
|
||||||
int parameterIndex = parameter + methodParamCount - (visible ? visibleAnnotableParameterCount : invisibleAnnotableParameterCount);
|
int parameterIndex = parameter + methodParamCount - (visible ? visibleAnnotableParameterCount : invisibleAnnotableParameterCount);
|
||||||
|
|||||||
+11
-6
@@ -15,12 +15,12 @@ import org.jetbrains.kotlin.backend.jvm.ir.isInPublicInlineScope
|
|||||||
import org.jetbrains.kotlin.backend.jvm.ir.javaClassReference
|
import org.jetbrains.kotlin.backend.jvm.ir.javaClassReference
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
@@ -136,11 +136,16 @@ class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext,
|
|||||||
}.also { it.parent = implClass }
|
}.also { it.parent = implClass }
|
||||||
|
|
||||||
val parameter = generatedConstructor.addValueParameter(propName.asString(), propType)
|
val parameter = generatedConstructor.addValueParameter(propName.asString(), propType)
|
||||||
// VALUE_FROM_PARAMETER
|
|
||||||
val originalParameter = ((property.backingField?.initializer?.expression as? IrGetValue)?.symbol?.owner as? IrValueParameter)
|
val defaultExpression = property.backingField?.initializer?.expression
|
||||||
if (originalParameter?.defaultValue != null) {
|
val newDefaultValue: IrExpressionBody? =
|
||||||
parameter.defaultValue = originalParameter.defaultValue!!.deepCopyWithVariables().also { it.transformChildrenVoid() }
|
if (defaultExpression is IrGetValue && defaultExpression.symbol.owner is IrValueParameter) {
|
||||||
}
|
// INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||||
|
(defaultExpression.symbol.owner as IrValueParameter).defaultValue
|
||||||
|
} else if (defaultExpression != null) {
|
||||||
|
property.backingField!!.initializer
|
||||||
|
} else null
|
||||||
|
parameter.defaultValue = newDefaultValue?.deepCopyWithVariables()?.also { it.transformChildrenVoid() }
|
||||||
|
|
||||||
ctorBody.statements += IrSetFieldImpl(
|
ctorBody.statements += IrSetFieldImpl(
|
||||||
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, field.symbol,
|
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, field.symbol,
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// IGNORE_DEXING
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// !LANGUAGE: +InstantiationOfAnnotationClasses
|
||||||
|
|
||||||
|
// MODULE: lib
|
||||||
|
// FILE: lib.kt
|
||||||
|
|
||||||
|
package a
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
annotation class A(val kClass: KClass<*> = Int::class)
|
||||||
|
|
||||||
|
annotation class OtherArrays(
|
||||||
|
val doublesArray: DoubleArray = [],
|
||||||
|
val enumArray: Array<kotlin.text.RegexOption> = [],
|
||||||
|
val annotationsArray: Array<JvmStatic> = [],
|
||||||
|
val namesArray: Array<JvmName> = [JvmName("foo")]
|
||||||
|
)
|
||||||
|
|
||||||
|
// Uncomment when KT-49998 is resolved
|
||||||
|
//annotation class UnsignedValue(
|
||||||
|
// val uint: UInt = 2147483657U // Int.MAX_VALUE + 10
|
||||||
|
//)
|
||||||
|
|
||||||
|
// MODULE: app(lib)
|
||||||
|
// FILE: app.kt
|
||||||
|
|
||||||
|
// kotlin.Metadata: IntArray, Array<String>
|
||||||
|
// kotlin.Deprecated: Nested annotation, enum instance
|
||||||
|
// a.A: KClass
|
||||||
|
// a.OtherArrays: Arrays of enums and other annotations
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
import a.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun one(): A = A()
|
||||||
|
fun two(): Metadata = Metadata()
|
||||||
|
fun three(): Deprecated = Deprecated("foo")
|
||||||
|
fun four(): OtherArrays = OtherArrays()
|
||||||
|
// fun five(): UnsignedValue = UnsignedValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = C().one()
|
||||||
|
assertEquals(Int::class, a.kClass)
|
||||||
|
assertEquals(
|
||||||
|
"""@kotlin.Metadata(bytecodeVersion=[1, 0, 3], data1=[], data2=[], extraInt=0, extraString=, kind=1, metadataVersion=[], packageName=)""",
|
||||||
|
C().two().toString()
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
"""@kotlin.Deprecated(level=WARNING, message=foo, replaceWith=@kotlin.ReplaceWith(expression=, imports=[]))""",
|
||||||
|
C().three().toString()
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
"""@a.OtherArrays(annotationsArray=[], doublesArray=[], enumArray=[], namesArray=[@kotlin.jvm.JvmName(name=foo)])""",
|
||||||
|
C().four().toString()
|
||||||
|
)
|
||||||
|
// assertEquals(Int.MAX_VALUE.toUInt() + 10.toUInt(), C().five().uint)
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+2
@@ -1,4 +1,6 @@
|
|||||||
// ALLOW_AST_ACCESS
|
// ALLOW_AST_ACCESS
|
||||||
|
// NO_CHECK_SOURCE_VS_BINARY
|
||||||
|
//^ While compiling source, we do not store annotation default values, but we load them when reading compiled files
|
||||||
package test
|
package test
|
||||||
|
|
||||||
annotation class Anno(val value: String = "0", val x: Int = 0)
|
annotation class Anno(val value: String = "0", val x: Int = 0)
|
||||||
|
|||||||
+2
-2
@@ -2,9 +2,9 @@ package test
|
|||||||
|
|
||||||
public final annotation class Anno : kotlin.Annotation {
|
public final annotation class Anno : kotlin.Annotation {
|
||||||
/*primary*/ public constructor Anno(/*0*/ value: kotlin.String = ..., /*1*/ x: kotlin.Int = ...)
|
/*primary*/ public constructor Anno(/*0*/ value: kotlin.String = ..., /*1*/ x: kotlin.Int = ...)
|
||||||
public final val value: kotlin.String
|
public final val value: kotlin.String = "0"
|
||||||
public final fun <get-value>(): kotlin.String
|
public final fun <get-value>(): kotlin.String
|
||||||
public final val x: kotlin.Int
|
public final val x: kotlin.Int = 0
|
||||||
public final fun <get-x>(): kotlin.Int
|
public final fun <get-x>(): kotlin.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
//ALLOW_AST_ACCESS
|
//ALLOW_AST_ACCESS
|
||||||
|
// NO_CHECK_SOURCE_VS_BINARY
|
||||||
|
//^ While compiling source, we do not store annotation default values, but we load them when reading compiled files
|
||||||
package test
|
package test
|
||||||
|
|
||||||
@Target(AnnotationTarget.TYPEALIAS)
|
@Target(AnnotationTarget.TYPEALIAS)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package test
|
|||||||
|
|
||||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPEALIAS}) public final annotation class Ann : kotlin.Annotation {
|
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPEALIAS}) public final annotation class Ann : kotlin.Annotation {
|
||||||
/*primary*/ public constructor Ann(/*0*/ value: kotlin.String = ...)
|
/*primary*/ public constructor Ann(/*0*/ value: kotlin.String = ...)
|
||||||
public final val value: kotlin.String
|
public final val value: kotlin.String = ""
|
||||||
public final fun <get-value>(): kotlin.String
|
public final fun <get-value>(): kotlin.String
|
||||||
}
|
}
|
||||||
@test.Ann public typealias A1 = kotlin.String
|
@test.Ann public typealias A1 = kotlin.String
|
||||||
|
|||||||
+6
@@ -467,6 +467,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt");
|
runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multimoduleCreation.kt")
|
||||||
|
public void testMultimoduleCreation() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/annotations/instances/multimoduleCreation.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("multimoduleInlining.kt")
|
@TestMetadata("multimoduleInlining.kt")
|
||||||
public void testMultimoduleInlining() throws Exception {
|
public void testMultimoduleInlining() throws Exception {
|
||||||
|
|||||||
+42
-6
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantL
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
||||||
storageManager: StorageManager,
|
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 loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): A
|
||||||
|
|
||||||
|
protected abstract fun loadAnnotationMethodDefaultValue(
|
||||||
|
annotationClass: KotlinJvmBinaryClass,
|
||||||
|
methodSignature: MemberSignature,
|
||||||
|
visitResult: (C) -> Unit
|
||||||
|
): KotlinJvmBinaryClass.AnnotationArgumentVisitor?
|
||||||
|
|
||||||
private fun loadAnnotationIfNotSpecial(
|
private fun loadAnnotationIfNotSpecial(
|
||||||
annotationClassId: ClassId,
|
annotationClassId: ClassId,
|
||||||
source: SourceElement,
|
source: SourceElement,
|
||||||
@@ -210,7 +215,30 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
|||||||
return proto.getExtension(JvmProtoBuf.typeParameterAnnotation).map { loadTypeAnnotation(it, nameResolver) }
|
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? {
|
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(
|
val specialCase = getSpecialCaseContainerClass(
|
||||||
container,
|
container,
|
||||||
property = true,
|
property = true,
|
||||||
@@ -225,11 +253,11 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
|||||||
)
|
)
|
||||||
val signature =
|
val signature =
|
||||||
getCallableSignature(
|
getCallableSignature(
|
||||||
proto, container.nameResolver, container.typeTable, AnnotatedCallableKind.PROPERTY, requireHasFieldFlag
|
proto, container.nameResolver, container.typeTable, annotatedCallableKind, requireHasFieldFlag
|
||||||
) ?: return null
|
) ?: return null
|
||||||
|
|
||||||
val constant = storage(kotlinClass).propertyConstants[signature] ?: return null
|
val result = storage(kotlinClass).loader(signature) ?: return null
|
||||||
return if (UnsignedTypes.isUnsignedType(expectedType)) transformToUnsignedConstant(constant) else constant
|
return if (UnsignedTypes.isUnsignedType(expectedType)) transformToUnsignedConstant(result) else result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findClassWithAnnotationsAndInitializers(
|
private fun findClassWithAnnotationsAndInitializers(
|
||||||
@@ -291,6 +319,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
|||||||
private fun loadAnnotationsAndInitializers(kotlinClass: KotlinJvmBinaryClass): Storage<A, C> {
|
private fun loadAnnotationsAndInitializers(kotlinClass: KotlinJvmBinaryClass): Storage<A, C> {
|
||||||
val memberAnnotations = HashMap<MemberSignature, MutableList<A>>()
|
val memberAnnotations = HashMap<MemberSignature, MutableList<A>>()
|
||||||
val propertyConstants = HashMap<MemberSignature, C>()
|
val propertyConstants = HashMap<MemberSignature, C>()
|
||||||
|
val annotationParametersDefaultValues = HashMap<MemberSignature, C>()
|
||||||
|
|
||||||
kotlinClass.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor {
|
kotlinClass.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor {
|
||||||
override fun visitMethod(name: Name, desc: String): KotlinJvmBinaryClass.MethodAnnotationVisitor? {
|
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)
|
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 {
|
open inner class MemberAnnotationVisitor(protected val signature: MemberSignature) : KotlinJvmBinaryClass.AnnotationVisitor {
|
||||||
@@ -340,7 +375,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
|||||||
}
|
}
|
||||||
}, getCachedFileContent(kotlinClass))
|
}, getCachedFileContent(kotlinClass))
|
||||||
|
|
||||||
return Storage(memberAnnotations, propertyConstants)
|
return Storage(memberAnnotations, propertyConstants, annotationParametersDefaultValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPropertySignature(
|
private fun getPropertySignature(
|
||||||
@@ -415,6 +450,7 @@ abstract class AbstractBinaryClassAnnotationAndConstantLoader<A : Any, C : Any>(
|
|||||||
|
|
||||||
private class Storage<out A, out C>(
|
private class Storage<out A, out C>(
|
||||||
val memberAnnotations: Map<MemberSignature, List<A>>,
|
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.metadata.deserialization.NameResolver
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.constants.*
|
import org.jetbrains.kotlin.resolve.constants.*
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer
|
import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.utils.compact
|
import org.jetbrains.kotlin.utils.compact
|
||||||
|
|
||||||
class BinaryClassAnnotationAndConstantLoaderImpl(
|
class BinaryClassAnnotationAndConstantLoaderImpl(
|
||||||
@@ -66,73 +70,24 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
|||||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||||
val annotationClass = resolveClass(annotationClassId)
|
val annotationClass = resolveClass(annotationClassId)
|
||||||
|
|
||||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
return object : AbstractAnnotationArgumentVisitor() {
|
||||||
private val arguments = HashMap<Name, ConstantValue<*>>()
|
private val arguments = HashMap<Name, ConstantValue<*>>()
|
||||||
|
|
||||||
override fun visit(name: Name?, value: Any?) {
|
override fun visitConstantValue(name: Name?, value: ConstantValue<*>) {
|
||||||
if (name != null) {
|
if (name != null) arguments[name] = value
|
||||||
arguments[name] = createConstant(name, value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitClassLiteral(name: Name, value: ClassLiteralValue) {
|
override fun visitArrayValue(name: Name?, elements: ArrayList<ConstantValue<*>>) {
|
||||||
arguments[name] = KClassValue(value)
|
if (name == null) return
|
||||||
}
|
val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass)
|
||||||
|
if (parameter != null) {
|
||||||
override fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name) {
|
arguments[name] = ConstantValueFactory.createArrayValue(elements.compact(), parameter.type)
|
||||||
arguments[name] = EnumValue(enumClassId, enumEntryName)
|
} 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.
|
||||||
override fun visitArray(name: Name): AnnotationArrayArgumentVisitor? {
|
// E.g. if we see `@Foo.Container(@Foo(1), @Foo(2))` in the bytecode on some declaration where `Foo` is some
|
||||||
return object : AnnotationArrayArgumentVisitor {
|
// Kotlin-repeatable annotation, we want to read annotations on that declaration as a list `[@Foo(1), @Foo(2)]`.
|
||||||
private val elements = ArrayList<ConstantValue<*>>()
|
elements.filterIsInstance<AnnotationValue>().mapTo(result, AnnotationValue::value)
|
||||||
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,14 +103,123 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
|
|||||||
|
|
||||||
result.add(AnnotationDescriptorImpl(annotationClass.defaultType, arguments, source))
|
result.add(AnnotationDescriptorImpl(annotationClass.defaultType, arguments, source))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createConstant(name: Name?, value: Any?): ConstantValue<*> {
|
override fun loadAnnotationMethodDefaultValue(
|
||||||
return ConstantValueFactory.createConstantValue(value)
|
annotationClass: KotlinJvmBinaryClass,
|
||||||
?: ErrorValue.create("Unsupported annotation argument: $name")
|
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 {
|
private fun resolveClass(classId: ClassId): ClassDescriptor {
|
||||||
return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses)
|
return module.findNonGenericClassAcrossDependencies(classId, notFoundClasses)
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-15
@@ -168,13 +168,13 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitClassLiteral(@NotNull Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
public void visitClassLiteral(@Nullable Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
|
public AnnotationArrayArgumentVisitor visitArray(@Nullable Name name) {
|
||||||
String string = name.asString();
|
String string = name != null ? name.asString() : null;
|
||||||
if (METADATA_DATA_FIELD_NAME.equals(string)) {
|
if (METADATA_DATA_FIELD_NAME.equals(string)) {
|
||||||
return dataArrayVisitor();
|
return dataArrayVisitor();
|
||||||
}
|
}
|
||||||
@@ -207,12 +207,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public AnnotationArgumentVisitor visitAnnotation(@NotNull Name name, @NotNull ClassId classId) {
|
public AnnotationArgumentVisitor visitAnnotation(@Nullable Name name, @NotNull ClassId classId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,13 +238,13 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitClassLiteral(@NotNull Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
public void visitClassLiteral(@Nullable Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
|
public AnnotationArrayArgumentVisitor visitArray(@Nullable Name name) {
|
||||||
String string = name.asString();
|
String string = name != null ? name.asString() : null;
|
||||||
if ("data".equals(string) || "filePartClassNames".equals(string)) {
|
if ("data".equals(string) || "filePartClassNames".equals(string)) {
|
||||||
return dataArrayVisitor();
|
return dataArrayVisitor();
|
||||||
}
|
}
|
||||||
@@ -277,12 +277,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public AnnotationArgumentVisitor visitAnnotation(@NotNull Name name, @NotNull ClassId classId) {
|
public AnnotationArgumentVisitor visitAnnotation(@Nullable Name name, @NotNull ClassId classId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,13 +297,13 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitClassLiteral(@NotNull Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
public void visitClassLiteral(@Nullable Name name, @NotNull ClassLiteralValue classLiteralValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
|
public AnnotationArrayArgumentVisitor visitArray(@Nullable Name name) {
|
||||||
String string = name.asString();
|
String string = name != null ? name.asString() : null;
|
||||||
if (SERIALIZED_IR_BYTES_FIELD_NAME.equals(string)) {
|
if (SERIALIZED_IR_BYTES_FIELD_NAME.equals(string)) {
|
||||||
return serializedIrArrayVisitor();
|
return serializedIrArrayVisitor();
|
||||||
}
|
}
|
||||||
@@ -323,12 +323,12 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public AnnotationArgumentVisitor visitAnnotation(@NotNull Name name, @NotNull ClassId classId) {
|
public AnnotationArgumentVisitor visitAnnotation(@Nullable Name name, @NotNull ClassId classId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-4
@@ -44,18 +44,20 @@ interface KotlinJvmBinaryClass {
|
|||||||
|
|
||||||
interface MethodAnnotationVisitor : AnnotationVisitor {
|
interface MethodAnnotationVisitor : AnnotationVisitor {
|
||||||
fun visitParameterAnnotation(index: Int, classId: ClassId, source: SourceElement): AnnotationArgumentVisitor?
|
fun visitParameterAnnotation(index: Int, classId: ClassId, source: SourceElement): AnnotationArgumentVisitor?
|
||||||
|
|
||||||
|
fun visitAnnotationMemberDefaultValue(): AnnotationArgumentVisitor?
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AnnotationArgumentVisitor {
|
interface AnnotationArgumentVisitor {
|
||||||
fun visit(name: Name?, value: Any?)
|
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()
|
fun visitEnd()
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -78,4 +78,10 @@ interface AnnotationAndConstantLoader<out A : Any, out C : Any> {
|
|||||||
proto: ProtoBuf.Property,
|
proto: ProtoBuf.Property,
|
||||||
expectedType: KotlinType
|
expectedType: KotlinType
|
||||||
): C?
|
): 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
|
val value = proto.getExtensionOrNull(protocol.compileTimeValue) ?: return null
|
||||||
return deserializer.resolveValue(expectedType, value, container.nameResolver)
|
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(
|
property.initialize(
|
||||||
getter, setter,
|
getter, setter,
|
||||||
FieldDescriptorImpl(getPropertyFieldAnnotations(proto, isDelegate = false), property),
|
FieldDescriptorImpl(getPropertyFieldAnnotations(proto, isDelegate = false), property),
|
||||||
|
|||||||
Reference in New Issue
Block a user