Do not store ClassDescriptor in EnumValue

Only store the ClassId of the enum class and the Name of the entry, and
resolve the needed descriptor in getType() instead, which now takes the
module instance where that descriptor should be resolved
This commit is contained in:
Alexander Udalov
2017-12-29 16:45:34 +01:00
parent 9290d58ed0
commit 82574cb570
25 changed files with 99 additions and 167 deletions
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.Jsr305State
import org.jetbrains.kotlin.utils.ReportLevel
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
private val TYPE_QUALIFIER_NICKNAME_FQNAME = FqName("javax.annotation.meta.TypeQualifierNickname")
private val TYPE_QUALIFIER_FQNAME = FqName("javax.annotation.meta.TypeQualifier")
@@ -148,12 +147,12 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager, private va
}
private fun ClassDescriptor.migrationAnnotationStatus(): ReportLevel? {
val stateDescriptor = annotations.findAnnotation(MIGRATION_ANNOTATION_FQNAME)?.firstArgument()?.safeAs<EnumValue>()?.value
?: return null
val enumValue = annotations.findAnnotation(MIGRATION_ANNOTATION_FQNAME)?.firstArgument() as? EnumValue
?: return null
jsr305State.migration?.let { return jsr305State.migration }
jsr305State.migration?.let { return it }
return when (stateDescriptor.name.asString()) {
return when (enumValue.enumEntryName.asString()) {
"STRICT" -> ReportLevel.STRICT
"WARN" -> ReportLevel.WARN
"IGNORE" -> ReportLevel.IGNORE
@@ -165,7 +164,7 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager, private va
when (this) {
is ArrayValue -> value.flatMap { it.mapConstantToQualifierApplicabilityTypes() }
is EnumValue -> listOfNotNull(
when (value.name.identifier) {
when (enumEntryName.identifier) {
"METHOD" -> QualifierApplicabilityType.METHOD_RETURN_TYPE
"FIELD" -> QualifierApplicabilityType.FIELD
"PARAMETER" -> QualifierApplicabilityType.VALUE_PARAMETER
@@ -124,8 +124,8 @@ class JavaTargetAnnotationDescriptor(
): JavaAnnotationDescriptor(c, annotation, KotlinBuiltIns.FQ_NAMES.target) {
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)
is JavaArrayAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(firstArgument.getElements())
is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(listOf(firstArgument))
else -> null
}
targetArgument?.let { mapOf(JavaAnnotationMapper.TARGET_ANNOTATION_ALLOWED_TARGETS to it) }.orEmpty()
@@ -137,7 +137,7 @@ class JavaRetentionAnnotationDescriptor(
c: LazyJavaResolverContext
): JavaAnnotationDescriptor(c, annotation, KotlinBuiltIns.FQ_NAMES.retention) {
override val allValueArguments by c.storageManager.createLazyValue {
val retentionArgument = JavaAnnotationTargetMapper.mapJavaRetentionArgument(firstArgument, c.module.builtIns)
val retentionArgument = JavaAnnotationTargetMapper.mapJavaRetentionArgument(firstArgument)
retentionArgument?.let { mapOf(JavaAnnotationMapper.RETENTION_ANNOTATION_VALUE to it) }.orEmpty()
}
}
@@ -159,17 +159,20 @@ object JavaAnnotationTargetMapper {
fun mapJavaTargetArgumentByName(argumentName: String?): Set<KotlinTarget> = targetNameLists[argumentName] ?: emptySet()
internal fun mapJavaTargetArguments(arguments: List<JavaAnnotationArgument>, builtIns: KotlinBuiltIns): ConstantValue<*> {
internal fun mapJavaTargetArguments(arguments: List<JavaAnnotationArgument>): ConstantValue<*> {
// Map arguments: java.lang.annotation.Target -> kotlin.annotation.Target
val kotlinTargets = arguments.filterIsInstance<JavaEnumValueAnnotationArgument>()
.flatMap { mapJavaTargetArgumentByName(it.entryName?.asString()) }
.mapNotNull { builtIns.getAnnotationTargetEnumEntry(it) }
.map(::EnumValue)
val parameterDescriptor = DescriptorResolverUtils.getAnnotationParameterByName(
JavaAnnotationMapper.TARGET_ANNOTATION_ALLOWED_TARGETS,
builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.target)
)
return ArrayValue(kotlinTargets) { parameterDescriptor?.type ?: ErrorUtils.createErrorType("Error: AnnotationTarget[]") }
.map { kotlinTarget ->
EnumValue(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.annotationTarget), Name.identifier(kotlinTarget.name))
}
return ArrayValue(kotlinTargets) { module ->
val parameterDescriptor = DescriptorResolverUtils.getAnnotationParameterByName(
JavaAnnotationMapper.TARGET_ANNOTATION_ALLOWED_TARGETS,
module.builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.target)
)
parameterDescriptor?.type ?: ErrorUtils.createErrorType("Error: AnnotationTarget[]")
}
}
private val retentionNameList = mapOf(
@@ -178,11 +181,11 @@ object JavaAnnotationTargetMapper {
"SOURCE" to KotlinRetention.SOURCE
)
internal fun mapJavaRetentionArgument(element: JavaAnnotationArgument?, builtIns: KotlinBuiltIns): ConstantValue<*>? {
// Map argument: java.lang.annotation.Retention -> kotlin.annotation.annotation
internal fun mapJavaRetentionArgument(element: JavaAnnotationArgument?): ConstantValue<*>? {
// Map argument: java.lang.annotation.Retention -> kotlin.annotation.Retention
return (element as? JavaEnumValueAnnotationArgument)?.let {
retentionNameList[it.entryName?.asString()]?.let {
builtIns.getAnnotationRetentionEnumEntry(it)?.let(::EnumValue)
retentionNameList[it.entryName?.asString()]?.let { retention ->
EnumValue(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.annotationRetention), Name.identifier(retention.name))
}
}
}
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.load.java.lazy.descriptors
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.findNonGenericClassAcrossDependencies
@@ -34,6 +33,7 @@ import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.renderer.DescriptorRenderer
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.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
import org.jetbrains.kotlin.storage.getValue
@@ -98,21 +98,9 @@ class LazyJavaAnnotationDescriptor(
}
private fun resolveFromEnumValue(enumClassId: ClassId?, entryName: Name?): ConstantValue<*>? {
if (entryName == null) return null
if (enumClassId == null || entryName == null) return null
if (enumClassId == null) {
return ConstantValueFactory.createEnumValue(ErrorUtils.createErrorClassWithExactName(entryName))
}
val enumClass = c.module.findNonGenericClassAcrossDependencies(
enumClassId,
c.components.deserializedDescriptorResolver.components.notFoundClasses
)
val classifier = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(entryName, NoLookupLocation.FROM_JAVA_LOADER)
as? ClassDescriptor ?: return null
return ConstantValueFactory.createEnumValue(classifier)
return EnumValue(enumClassId, entryName)
}
private fun resolveFromJavaClassObjectType(javaType: JavaType): ConstantValue<*>? {
@@ -50,11 +50,11 @@ class SignatureEnhancement(
) {
private fun AnnotationDescriptor.extractNullabilityTypeFromArgument(): NullabilityQualifierWithMigrationStatus? {
val enumEntryDescriptor = firstArgument().safeAs<EnumValue>()?.value
// if no argument is specified, use default value: NOT_NULL
?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
val enumValue = firstArgument() as? EnumValue
// if no argument is specified, use default value: NOT_NULL
?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
return when (enumEntryDescriptor.name.asString()) {
return when (enumValue.enumEntryName.asString()) {
"ALWAYS" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
"MAYBE", "NEVER" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE)
"UNKNOWN" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY)
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor
import org.jetbrains.kotlin.name.ClassId
@@ -29,6 +28,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.AnnotationValue
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.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
@@ -97,7 +97,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
}
override fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name) {
arguments[name] = enumEntryValue(enumClassId, enumEntryName)
arguments[name] = EnumValue(enumClassId, enumEntryName)
}
override fun visitArray(name: Name): AnnotationArrayArgumentVisitor? {
@@ -109,7 +109,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
}
override fun visitEnum(enumClassId: ClassId, enumEntryName: Name) {
elements.add(enumEntryValue(enumClassId, enumEntryName))
elements.add(EnumValue(enumClassId, enumEntryName))
}
override fun visitEnd() {
@@ -132,18 +132,6 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
}
}
// NOTE: see analogous code in AnnotationDeserializer
private fun enumEntryValue(enumClassId: ClassId, name: Name): ConstantValue<*> {
val enumClass = resolveClass(enumClassId)
if (enumClass.kind == ClassKind.ENUM_CLASS) {
val classifier = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(name, NoLookupLocation.FROM_JAVA_LOADER)
if (classifier is ClassDescriptor) {
return ConstantValueFactory.createEnumValue(classifier)
}
}
return ConstantValueFactory.createErrorValue("Unresolved enum entry: $enumClassId.$name")
}
override fun visitEnd() {
result.add(AnnotationDescriptorImpl(annotationClass.defaultType, arguments, source))
}