kotlin.reflect.jvm.internal.impl.load.kotlin.BinaryClassAnnotationAndConstantLoaderImpl.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package kotlin.reflect.jvm.internal.impl.load.kotlin
import kotlin.reflect.jvm.internal.impl.descriptors.*
import kotlin.reflect.jvm.internal.impl.descriptors.annotations.AnnotationDescriptor
import kotlin.reflect.jvm.internal.impl.descriptors.annotations.AnnotationDescriptorImpl
import kotlin.reflect.jvm.internal.impl.descriptors.annotations.AnnotationUseSiteTarget
import kotlin.reflect.jvm.internal.impl.descriptors.annotations.AnnotationWithTarget
import kotlin.reflect.jvm.internal.impl.load.java.components.DescriptorResolverUtils
import kotlin.reflect.jvm.internal.impl.load.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor
import kotlin.reflect.jvm.internal.impl.name.ClassId
import kotlin.reflect.jvm.internal.impl.name.Name
import kotlin.reflect.jvm.internal.impl.resolve.constants.AnnotationValue
import kotlin.reflect.jvm.internal.impl.resolve.constants.ConstantValue
import kotlin.reflect.jvm.internal.impl.resolve.constants.ConstantValueFactory
import kotlin.reflect.jvm.internal.impl.serialization.ProtoBuf
import kotlin.reflect.jvm.internal.impl.serialization.deserialization.AnnotationDeserializer
import kotlin.reflect.jvm.internal.impl.serialization.deserialization.ErrorReporter
import kotlin.reflect.jvm.internal.impl.serialization.deserialization.NameResolver
import kotlin.reflect.jvm.internal.impl.serialization.deserialization.findClassAcrossModuleDependencies
import kotlin.reflect.jvm.internal.impl.serialization.jvm.JvmProtoBuf
import kotlin.reflect.jvm.internal.impl.storage.StorageManager
import kotlin.reflect.jvm.internal.impl.types.ErrorUtils
import java.util.ArrayList
import java.util.HashMap
public class BinaryClassAnnotationAndConstantLoaderImpl(
private val module: ModuleDescriptor,
storageManager: StorageManager,
kotlinClassFinder: KotlinClassFinder,
errorReporter: ErrorReporter
) : AbstractBinaryClassAnnotationAndConstantLoader, AnnotationWithTarget>(
storageManager, kotlinClassFinder, errorReporter
) {
private val annotationDeserializer = AnnotationDeserializer(module)
private val factory = ConstantValueFactory(module.builtIns)
override fun loadClassAnnotations(
classProto: ProtoBuf.Class,
nameResolver: NameResolver
): List {
val binaryAnnotationDescriptors = super.loadClassAnnotations(classProto, nameResolver)
val serializedAnnotations = classProto.getExtension(JvmProtoBuf.classAnnotation).orEmpty()
val serializedAnnotationDescriptors = serializedAnnotations.map {
annotationDeserializer.deserializeAnnotation(it, nameResolver)
}
return binaryAnnotationDescriptors + serializedAnnotationDescriptors
}
override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor =
annotationDeserializer.deserializeAnnotation(proto, nameResolver)
override fun loadConstant(desc: String, initializer: Any): ConstantValue<*>? {
val normalizedValue: Any = if (desc in "ZBCS") {
val intValue = initializer as Int
when (desc) {
"Z" -> intValue != 0
"B" -> intValue.toByte()
"C" -> intValue.toChar()
"S" -> intValue.toShort()
else -> throw AssertionError(desc)
}
}
else {
initializer
}
return factory.createConstantValue(normalizedValue)
}
override fun loadPropertyAnnotations(
propertyAnnotations: List,
fieldAnnotations: List
): List {
return propertyAnnotations.map { AnnotationWithTarget(it, null) } +
fieldAnnotations.map { AnnotationWithTarget(it, AnnotationUseSiteTarget.FIELD) }
}
override fun transformAnnotations(annotations: List): List {
return annotations.map { AnnotationWithTarget(it, null) }
}
override fun loadAnnotation(
annotationClassId: ClassId,
source: SourceElement,
result: MutableList
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
val annotationClass = resolveClass(annotationClassId)
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor {
private val arguments = HashMap>()
override fun visit(name: Name?, value: Any?) {
if (name != null) {
setArgumentValueByName(name, createConstant(name, value))
}
}
override fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name) {
setArgumentValueByName(name, enumEntryValue(enumClassId, enumEntryName))
}
override fun visitArray(name: Name): AnnotationArrayArgumentVisitor? {
return object : KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor {
private val elements = ArrayList>()
override fun visit(value: Any?) {
elements.add(createConstant(name, value))
}
override fun visitEnum(enumClassId: ClassId, enumEntryName: Name) {
elements.add(enumEntryValue(enumClassId, enumEntryName))
}
override fun visitEnd() {
val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass)
if (parameter != null) {
elements.trimToSize()
arguments[parameter] = factory.createArrayValue(elements, parameter.getType())
}
}
}
}
override fun visitAnnotation(name: Name, classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
val list = ArrayList()
val visitor = loadAnnotation(classId, SourceElement.NO_SOURCE, list)!!
return object: KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
override fun visitEnd() {
visitor.visitEnd()
setArgumentValueByName(name, AnnotationValue(list.single()))
}
}
}
// NOTE: see analogous code in AnnotationDeserializer
private fun enumEntryValue(enumClassId: ClassId, name: Name): ConstantValue<*> {
val enumClass = resolveClass(enumClassId)
if (enumClass.getKind() == ClassKind.ENUM_CLASS) {
val classifier = enumClass.getUnsubstitutedInnerClassesScope().getClassifier(name)
if (classifier is ClassDescriptor) {
return factory.createEnumValue(classifier)
}
}
return factory.createErrorValue("Unresolved enum entry: $enumClassId.$name")
}
override fun visitEnd() {
result.add(AnnotationDescriptorImpl(annotationClass.getDefaultType(), arguments, source))
}
private fun createConstant(name: Name?, value: Any?): ConstantValue<*> {
return factory.createConstantValue(value) ?:
factory.createErrorValue("Unsupported annotation argument: $name")
}
private fun setArgumentValueByName(name: Name, argumentValue: ConstantValue<*>) {
val parameter = DescriptorResolverUtils.getAnnotationParameterByName(name, annotationClass)
if (parameter != null) {
arguments[parameter] = argumentValue
}
}
}
}
private fun resolveClass(classId: ClassId): ClassDescriptor {
return module.findClassAcrossModuleDependencies(classId)
?: ErrorUtils.createErrorClass(classId.asSingleFqName().asString())
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy