J2K AnnotationDescriptor, refactor implementations

This commit is contained in:
Alexander Udalov
2017-07-04 14:14:36 +03:00
parent 7ec67505c5
commit 1d64b61a8f
6 changed files with 52 additions and 91 deletions
@@ -33,7 +33,9 @@ import org.jetbrains.kotlin.resolve.constants.ArrayValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.SimpleType
import java.lang.annotation.Documented
import java.lang.annotation.Retention
import java.lang.annotation.Target
@@ -98,41 +100,37 @@ open class JavaAnnotationDescriptor(
annotation: JavaAnnotation?,
private val kotlinAnnotationClassDescriptor: ClassDescriptor
): AnnotationDescriptor {
private val source = annotation?.let { c.components.sourceElementFactory.source(it) } ?: SourceElement.NO_SOURCE
override val source: SourceElement = annotation?.let { c.components.sourceElementFactory.source(it) } ?: SourceElement.NO_SOURCE
override fun getType() = kotlinAnnotationClassDescriptor.defaultType
override fun getSource() = source
override val type: SimpleType get() = kotlinAnnotationClassDescriptor.defaultType
protected val valueParameters: List<ValueParameterDescriptor>
get() = kotlinAnnotationClassDescriptor.constructors.single().valueParameters
protected val firstArgument: JavaAnnotationArgument? = annotation?.arguments?.firstOrNull()
override fun getAllValueArguments() = emptyMap<ValueParameterDescriptor, ConstantValue<*>?>()
override val allValueArguments: Map<ValueParameterDescriptor, ConstantValue<*>> get() = emptyMap()
}
class JavaDeprecatedAnnotationDescriptor(
annotation: JavaAnnotation?,
c: LazyJavaResolverContext
): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.deprecatedAnnotation) {
private val valueArguments = c.storageManager.createLazyValue {
override val allValueArguments: Map<ValueParameterDescriptor, ConstantValue<*>> by c.storageManager.createLazyValue {
val parameterDescriptor = valueParameters.firstOrNull {
it.name == JavaAnnotationMapper.DEPRECATED_ANNOTATION_MESSAGE
}
parameterDescriptor?.let { mapOf(it to ConstantValueFactory(c.module.builtIns).createConstantValue("Deprecated in Java")) } ?: emptyMap()
parameterDescriptor?.let {
mapOf(it to ConstantValueFactory(c.module.builtIns).createStringValue("Deprecated in Java"))
}.orEmpty()
}
override fun getAllValueArguments() = valueArguments()
}
class JavaTargetAnnotationDescriptor(
annotation: JavaAnnotation,
c: LazyJavaResolverContext
): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.targetAnnotation) {
private val valueArguments = c.storageManager.createLazyValue {
override val allValueArguments by c.storageManager.createLazyValue {
val targetArgument = when (firstArgument) {
is JavaArrayAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(firstArgument.getElements(), c.module.builtIns)
is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(listOf(firstArgument), c.module.builtIns)
@@ -140,24 +138,16 @@ class JavaTargetAnnotationDescriptor(
}
mapOf(valueParameters.single() to targetArgument)
}
override fun getAllValueArguments() = valueArguments()
}
class JavaRetentionAnnotationDescriptor(
annotation: JavaAnnotation,
c: LazyJavaResolverContext
): JavaAnnotationDescriptor(c, annotation, c.module.builtIns.retentionAnnotation) {
private val valueArguments = c.storageManager.createLazyValue {
val retentionArgument = when (firstArgument) {
is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaRetentionArgument(firstArgument, c.module.builtIns)
else -> return@createLazyValue emptyMap<ValueParameterDescriptor, ConstantValue<*>>()
}
mapOf(valueParameters.single() to retentionArgument)
override val allValueArguments by c.storageManager.createLazyValue {
val retentionArgument = JavaAnnotationTargetMapper.mapJavaRetentionArgument(firstArgument, c.module.builtIns)
retentionArgument?.let { mapOf(valueParameters.single() to it) }.orEmpty()
}
override fun getAllValueArguments() = valueArguments()
}
object JavaAnnotationTargetMapper {
@@ -177,7 +167,7 @@ object JavaAnnotationTargetMapper {
fun mapJavaTargetArgumentByName(argumentName: String?): Set<KotlinTarget> = targetNameLists[argumentName] ?: emptySet()
fun mapJavaTargetArguments(arguments: List<JavaAnnotationArgument>, builtIns: KotlinBuiltIns): ConstantValue<*>? {
internal fun mapJavaTargetArguments(arguments: List<JavaAnnotationArgument>, builtIns: KotlinBuiltIns): ConstantValue<*> {
// Map arguments: java.lang.annotation.Target -> kotlin.annotation.Target
val kotlinTargets = arguments.filterIsInstance<JavaEnumValueAnnotationArgument>()
.flatMap { mapJavaTargetArgumentByName(it.resolve()?.name?.asString()) }
@@ -195,11 +185,11 @@ object JavaAnnotationTargetMapper {
"SOURCE" to KotlinRetention.SOURCE
)
fun mapJavaRetentionArgument(element: JavaAnnotationArgument, builtIns: KotlinBuiltIns): ConstantValue<*>? {
internal fun mapJavaRetentionArgument(element: JavaAnnotationArgument?, builtIns: KotlinBuiltIns): ConstantValue<*>? {
// Map argument: java.lang.annotation.Retention -> kotlin.annotation.annotation
return (element as? JavaEnumValueAnnotationArgument)?.let {
retentionNameList[it.resolve()?.name?.asString()]?.let {
(builtIns.getAnnotationRetentionEnumEntry(it) as? ClassDescriptor)?.let(::EnumValue)
builtIns.getAnnotationRetentionEnumEntry(it)?.let(::EnumValue)
}
}
}
@@ -37,19 +37,20 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
class LazyJavaAnnotationDescriptor(
private val c: LazyJavaResolverContext,
val javaAnnotation: JavaAnnotation
private val javaAnnotation: JavaAnnotation
) : AnnotationDescriptor {
private val fqName = c.storageManager.createNullableLazyValue {
javaAnnotation.classId?.asSingleFqName()
}
private val type = c.storageManager.createLazyValue {
override val type by c.storageManager.createLazyValue {
val fqName = fqName() ?: return@createLazyValue ErrorUtils.createErrorType("No fqName: $javaAnnotation")
val annotationClass = JavaToKotlinClassMap.mapJavaToKotlin(fqName, c.module.builtIns)
?: javaAnnotation.resolve()?.let { javaClass -> c.components.moduleClassResolver.resolveClass(javaClass) }
@@ -57,27 +58,17 @@ class LazyJavaAnnotationDescriptor(
annotationClass.defaultType
}
private val source = c.components.sourceElementFactory.source(javaAnnotation)
override val source = c.components.sourceElementFactory.source(javaAnnotation)
private val factory = ConstantValueFactory(c.module.builtIns)
override fun getType(): KotlinType = type()
private val allValueArguments = c.storageManager.createLazyValue {
computeValueArguments()
}
override fun getAllValueArguments() = allValueArguments()
override fun getSource() = source
private fun computeValueArguments(): Map<ValueParameterDescriptor, ConstantValue<*>> {
val constructors = getAnnotationClass().constructors
if (constructors.isEmpty()) return mapOf()
override val allValueArguments by c.storageManager.createLazyValue {
val constructors = annotationClass!!.constructors
if (constructors.isEmpty()) return@createLazyValue emptyMap<ValueParameterDescriptor, ConstantValue<*>>()
val nameToArg = javaAnnotation.arguments.associateBy { it.name }
return constructors.first().valueParameters.keysToMapExceptNulls { valueParameter ->
constructors.first().valueParameters.keysToMapExceptNulls { valueParameter ->
var javaAnnotationArgument = nameToArg[valueParameter.name]
if (javaAnnotationArgument == null && valueParameter.name == DEFAULT_ANNOTATION_MEMBER_NAME) {
javaAnnotationArgument = nameToArg[null]
@@ -87,8 +78,6 @@ class LazyJavaAnnotationDescriptor(
}
}
private fun getAnnotationClass() = annotationClass!!
private fun resolveAnnotationArgument(argument: JavaAnnotationArgument?): ConstantValue<*>? {
return when (argument) {
is JavaLiteralAnnotationArgument -> factory.createConstantValue(argument.value)
@@ -105,9 +94,9 @@ class LazyJavaAnnotationDescriptor(
}
private fun resolveFromArray(argumentName: Name, elements: List<JavaAnnotationArgument>): ConstantValue<*>? {
if (getType().isError) return null
if (type.isError) return null
val valueParameter = DescriptorResolverUtils.getAnnotationParameterByName(argumentName, getAnnotationClass()) ?: return null
val valueParameter = DescriptorResolverUtils.getAnnotationParameterByName(argumentName, annotationClass!!) ?: return null
val values = elements.map {
argument -> resolveAnnotationArgument(argument) ?: factory.createNullValue()
@@ -123,7 +112,7 @@ class LazyJavaAnnotationDescriptor(
val enumClass = c.components.moduleClassResolver.resolveClass(containingJavaClass) ?: return null
val classifier = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(element.name, NoLookupLocation.FROM_JAVA_LOADER)
if (classifier !is ClassDescriptor) return null
as? ClassDescriptor ?: return null
return factory.createEnumValue(classifier)
}
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.load.java.typeEnhancement
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -30,6 +32,7 @@ import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifier.NOT_N
import org.jetbrains.kotlin.load.java.typeEnhancement.NullabilityQualifier.NULLABLE
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.createProjection
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
@@ -205,9 +208,9 @@ private class EnhancedTypeAnnotations(private val fqNameToMatch: FqName) : Annot
private object EnhancedTypeAnnotationDescriptor : AnnotationDescriptor {
private fun throwError(): Nothing = error("No methods should be called on this descriptor. Only its presence matters")
override fun getType() = throwError()
override fun getAllValueArguments() = throwError()
override fun getSource() = throwError()
override val type: KotlinType get() = throwError()
override val allValueArguments: Map<ValueParameterDescriptor, ConstantValue<*>> get() = throwError()
override val source: SourceElement get() = throwError()
override fun toString() = "[EnhancedType]"
}