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
@@ -438,7 +438,7 @@ public abstract class AnnotationCodegen {
} }
@Nullable @Nullable
private Set<ElementType> getJavaTargetList(ClassDescriptor descriptor) { private static Set<ElementType> getJavaTargetList(ClassDescriptor descriptor) {
AnnotationDescriptor targetAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Target.class.getName())); AnnotationDescriptor targetAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Target.class.getName()));
if (targetAnnotation != null) { if (targetAnnotation != null) {
Collection<ConstantValue<?>> valueArguments = targetAnnotation.getAllValueArguments().values(); Collection<ConstantValue<?>> valueArguments = targetAnnotation.getAllValueArguments().values();
@@ -449,12 +449,9 @@ public abstract class AnnotationCodegen {
Set<ElementType> result = EnumSet.noneOf(ElementType.class); Set<ElementType> result = EnumSet.noneOf(ElementType.class);
for (ConstantValue<?> value : values) { for (ConstantValue<?> value : values) {
if (value instanceof EnumValue) { if (value instanceof EnumValue) {
ClassDescriptor enumEntry = ((EnumValue) value).getValue(); FqName enumClassFqName = ((EnumValue) value).getEnumClassId().asSingleFqName();
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry); if (ElementType.class.getName().equals(enumClassFqName.asString())) {
if (classObjectType != null) { result.add(ElementType.valueOf(((EnumValue) value).getEnumEntryName().asString()));
if ("java/lang/annotation/ElementType".equals(typeMapper.mapType(classObjectType).getInternalName())) {
result.add(ElementType.valueOf(enumEntry.getName().asString()));
}
} }
} }
} }
@@ -466,21 +463,18 @@ public abstract class AnnotationCodegen {
} }
@NotNull @NotNull
private RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) { private static RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) {
KotlinRetention retention = DescriptorUtilsKt.getAnnotationRetention(descriptor); KotlinRetention retention = DescriptorUtilsKt.getAnnotationRetention(descriptor);
if (retention != null) { if (retention != null) {
return annotationRetentionMap.get(retention); return annotationRetentionMap.get(retention);
} }
AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName())); AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName()));
if (retentionAnnotation != null) { if (retentionAnnotation != null) {
ConstantValue<?> compileTimeConstant = CollectionsKt.firstOrNull(retentionAnnotation.getAllValueArguments().values()); ConstantValue<?> value = CollectionsKt.firstOrNull(retentionAnnotation.getAllValueArguments().values());
if (compileTimeConstant instanceof EnumValue) { if (value instanceof EnumValue) {
ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue(); FqName enumClassFqName = ((EnumValue) value).getEnumClassId().asSingleFqName();
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry); if (RetentionPolicy.class.getName().equals(enumClassFqName.asString())) {
if (classObjectType != null) { return RetentionPolicy.valueOf(((EnumValue) value).getEnumEntryName().asString());
if ("java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName())) {
return RetentionPolicy.valueOf(enumEntry.getName().asString());
}
} }
} }
} }
@@ -59,16 +59,18 @@ class JvmStringTable(private val typeMapper: KotlinTypeMapper) : StringTable {
throw IllegalStateException("Cannot get FQ name of error class: " + descriptor) throw IllegalStateException("Cannot get FQ name of error class: " + descriptor)
} }
// We use the following format to encode ClassId: "pkg/Outer.Inner". return getClassIdIndex(descriptor.classId)
// It represents a unique name, but such names don't usually appear in the constant pool, so we're writing "Lpkg/Outer$Inner;" }
// instead and an instruction to drop the first and the last character in this string and replace all '$' with '.'.
// This works most of the time, except in two rare cases:
// - the name of the class or any of its outer classes contains dollars. In this case we're just storing the described
// string literally: "pkg/Outer.Inner$with$dollars"
// - the class is local or nested in local. In this case we're also storing the literal string, and also storing the fact that
// this name represents a local class in a separate list
val classId = descriptor.classId // We use the following format to encode ClassId: "pkg/Outer.Inner".
// It represents a unique name, but such names don't usually appear in the constant pool, so we're writing "Lpkg/Outer$Inner;"
// instead and an instruction to drop the first and the last character in this string and replace all '$' with '.'.
// This works most of the time, except in two rare cases:
// - the name of the class or any of its outer classes contains dollars. In this case we're just storing the described
// string literally: "pkg/Outer.Inner$with$dollars"
// - the class is local or nested in local. In this case we're also storing the literal string, and also storing the fact that
// this name represents a local class in a separate list
override fun getClassIdIndex(classId: ClassId): Int {
val string = classId.asString() val string = classId.asString()
map[string]?.let { recordedIndex -> map[string]?.let { recordedIndex ->
@@ -108,11 +108,11 @@ public class MappingClassesForWhenByEnumCodegen {
v.putstatic(cb.getThisName(), mapping.getFieldName(), MAPPINGS_FIELD_DESCRIPTOR); v.putstatic(cb.getThisName(), mapping.getFieldName(), MAPPINGS_FIELD_DESCRIPTOR);
for (Map.Entry<EnumValue, Integer> item : mapping.enumValuesToIntMapping()) { for (Map.Entry<EnumValue, Integer> item : mapping.enumValuesToIntMapping()) {
EnumValue enumEntry = item.getKey(); EnumValue enumValue = item.getKey();
int mappedValue = item.getValue(); int mappedValue = item.getValue();
v.getstatic(cb.getThisName(), mapping.getFieldName(), MAPPINGS_FIELD_DESCRIPTOR); v.getstatic(cb.getThisName(), mapping.getFieldName(), MAPPINGS_FIELD_DESCRIPTOR);
v.getstatic(enumType.getInternalName(), enumEntry.getValue().getName().asString(), enumType.getDescriptor()); v.getstatic(enumType.getInternalName(), enumValue.getEnumEntryName().asString(), enumType.getDescriptor());
v.invokevirtual(enumType.getInternalName(), "ordinal", Type.getMethodDescriptor(Type.INT_TYPE), false); v.invokevirtual(enumType.getInternalName(), "ordinal", Type.getMethodDescriptor(Type.INT_TYPE), false);
v.iconst(mappedValue); v.iconst(mappedValue);
v.astore(Type.INT_TYPE); v.astore(Type.INT_TYPE);
@@ -208,7 +208,7 @@ class AnnotationChecker(
val valueArguments = targetEntryDescriptor.allValueArguments val valueArguments = targetEntryDescriptor.allValueArguments
val valueArgument = valueArguments.entries.firstOrNull()?.value as? ArrayValue ?: return null val valueArgument = valueArguments.entries.firstOrNull()?.value as? ArrayValue ?: return null
return valueArgument.value.filterIsInstance<EnumValue>().mapNotNull { return valueArgument.value.filterIsInstance<EnumValue>().mapNotNull {
KotlinTarget.valueOrNull(it.value.name.asString()) KotlinTarget.valueOrNull(it.enumEntryName.asString())
}.toSet() }.toSet()
} }
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.constants.* import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
@@ -662,7 +663,8 @@ private class ConstantExpressionEvaluatorVisitor(
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, expectedType: KotlinType?): CompileTimeConstant<*>? { override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
val enumDescriptor = trace.bindingContext.get(BindingContext.REFERENCE_TARGET, expression) val enumDescriptor = trace.bindingContext.get(BindingContext.REFERENCE_TARGET, expression)
if (enumDescriptor != null && DescriptorUtils.isEnumEntry(enumDescriptor)) { if (enumDescriptor != null && DescriptorUtils.isEnumEntry(enumDescriptor)) {
return ConstantValueFactory.createEnumValue(enumDescriptor as ClassDescriptor).wrap() val enumClassId = (enumDescriptor.containingDeclaration as ClassDescriptor).classId ?: return null
return EnumValue(enumClassId, enumDescriptor.name).wrap()
} }
val resolvedCall = expression.getResolvedCall(trace.bindingContext) val resolvedCall = expression.getResolvedCall(trace.bindingContext)
@@ -78,9 +78,8 @@ class AnnotationSerializer(private val stringTable: StringTable) {
override fun visitEnumValue(value: EnumValue, data: Unit) { override fun visitEnumValue(value: EnumValue, data: Unit) {
type = Type.ENUM type = Type.ENUM
val enumEntry = value.value classId = stringTable.getClassIdIndex(value.enumClassId)
classId = stringTable.getFqNameIndex(enumEntry.containingDeclaration as ClassDescriptor) enumValueId = stringTable.getStringIndex(value.enumEntryName.asString())
enumValueId = stringTable.getStringIndex(enumEntry.name.asString())
} }
override fun visitErrorValue(value: ErrorValue, data: Unit) { override fun visitErrorValue(value: ErrorValue, data: Unit) {
@@ -644,19 +644,19 @@ class DescriptorSerializer private constructor(
proto.message = stringTable.getStringIndex(message) proto.message = stringTable.getStringIndex(message)
} }
val level = (args[RequireKotlinNames.LEVEL] as? EnumValue)?.value?.name?.asString() val level = (args[RequireKotlinNames.LEVEL] as? EnumValue)?.enumEntryName?.asString()
when (level) { when (level) {
DeprecationLevel.ERROR.toString() -> { /* ERROR is the default level */ } DeprecationLevel.ERROR.name -> { /* ERROR is the default level */ }
DeprecationLevel.WARNING.toString() -> proto.level = ProtoBuf.VersionRequirement.Level.WARNING DeprecationLevel.WARNING.name -> proto.level = ProtoBuf.VersionRequirement.Level.WARNING
DeprecationLevel.HIDDEN.toString() -> proto.level = ProtoBuf.VersionRequirement.Level.HIDDEN DeprecationLevel.HIDDEN.name -> proto.level = ProtoBuf.VersionRequirement.Level.HIDDEN
} }
val versionKind = (args[RequireKotlinNames.VERSION_KIND] as? EnumValue)?.value?.name?.asString() val versionKind = (args[RequireKotlinNames.VERSION_KIND] as? EnumValue)?.enumEntryName?.asString()
when (versionKind) { when (versionKind) {
ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION.toString() -> { /* LANGUAGE_VERSION is the default kind */ } ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION.name -> { /* LANGUAGE_VERSION is the default kind */ }
ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION.toString() -> ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION.name ->
proto.versionKind = ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION proto.versionKind = ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION
ProtoBuf.VersionRequirement.VersionKind.API_VERSION.toString() -> ProtoBuf.VersionRequirement.VersionKind.API_VERSION.name ->
proto.versionKind = ProtoBuf.VersionRequirement.VersionKind.API_VERSION proto.versionKind = ProtoBuf.VersionRequirement.VersionKind.API_VERSION
} }
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.serialization package org.jetbrains.kotlin.serialization
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.name.ClassId
import java.io.OutputStream import java.io.OutputStream
interface StringTable { interface StringTable {
@@ -24,5 +25,7 @@ interface StringTable {
fun getFqNameIndex(descriptor: ClassifierDescriptorWithTypeParameters): Int fun getFqNameIndex(descriptor: ClassifierDescriptorWithTypeParameters): Int
fun getClassIdIndex(classId: ClassId): Int
fun serializeTo(output: OutputStream) fun serializeTo(output: OutputStream)
} }
@@ -62,7 +62,7 @@ open class StringTableImpl : StringTable {
return getClassIdIndex(classId) return getClassIdIndex(classId)
} }
fun getClassIdIndex(classId: ClassId): Int { override fun getClassIdIndex(classId: ClassId): Int {
val builder = QualifiedName.newBuilder() val builder = QualifiedName.newBuilder()
builder.kind = QualifiedName.Kind.CLASS builder.kind = QualifiedName.Kind.CLASS
@@ -5,7 +5,7 @@ public final annotation class Anno : kotlin.Annotation {
public final val e: test.E public final val e: test.E
} }
@test.Anno(e = Unresolved enum entry: test/E.ENTRY) public open class Class { @test.Anno(e = E.ENTRY) public open class Class {
public constructor Class() public constructor Class()
} }
@@ -169,8 +169,7 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() {
it.allValueArguments.forEach { it.allValueArguments.forEach {
val argument = it.value val argument = it.value
if (argument is EnumValue) { if (argument is EnumValue) {
Assert.assertEquals("Enum entry name should be <module-name>X", "X", argument.value.name.identifier.last().toString()) Assert.assertEquals("Enum entry name should be <module-name>X", "X", argument.enumEntryName.identifier.last().toString())
checkDescriptor(argument.value, callable)
} }
} }
} }
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.Jsr305State import org.jetbrains.kotlin.utils.Jsr305State
import org.jetbrains.kotlin.utils.ReportLevel import org.jetbrains.kotlin.utils.ReportLevel
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult 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_NICKNAME_FQNAME = FqName("javax.annotation.meta.TypeQualifierNickname")
private val TYPE_QUALIFIER_FQNAME = FqName("javax.annotation.meta.TypeQualifier") 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? { private fun ClassDescriptor.migrationAnnotationStatus(): ReportLevel? {
val stateDescriptor = annotations.findAnnotation(MIGRATION_ANNOTATION_FQNAME)?.firstArgument()?.safeAs<EnumValue>()?.value val enumValue = annotations.findAnnotation(MIGRATION_ANNOTATION_FQNAME)?.firstArgument() as? EnumValue
?: return null ?: 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 "STRICT" -> ReportLevel.STRICT
"WARN" -> ReportLevel.WARN "WARN" -> ReportLevel.WARN
"IGNORE" -> ReportLevel.IGNORE "IGNORE" -> ReportLevel.IGNORE
@@ -165,7 +164,7 @@ class AnnotationTypeQualifierResolver(storageManager: StorageManager, private va
when (this) { when (this) {
is ArrayValue -> value.flatMap { it.mapConstantToQualifierApplicabilityTypes() } is ArrayValue -> value.flatMap { it.mapConstantToQualifierApplicabilityTypes() }
is EnumValue -> listOfNotNull( is EnumValue -> listOfNotNull(
when (value.name.identifier) { when (enumEntryName.identifier) {
"METHOD" -> QualifierApplicabilityType.METHOD_RETURN_TYPE "METHOD" -> QualifierApplicabilityType.METHOD_RETURN_TYPE
"FIELD" -> QualifierApplicabilityType.FIELD "FIELD" -> QualifierApplicabilityType.FIELD
"PARAMETER" -> QualifierApplicabilityType.VALUE_PARAMETER "PARAMETER" -> QualifierApplicabilityType.VALUE_PARAMETER
@@ -124,8 +124,8 @@ class JavaTargetAnnotationDescriptor(
): JavaAnnotationDescriptor(c, annotation, KotlinBuiltIns.FQ_NAMES.target) { ): JavaAnnotationDescriptor(c, annotation, KotlinBuiltIns.FQ_NAMES.target) {
override val allValueArguments by c.storageManager.createLazyValue { override val allValueArguments by c.storageManager.createLazyValue {
val targetArgument = when (firstArgument) { val targetArgument = when (firstArgument) {
is JavaArrayAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(firstArgument.getElements(), c.module.builtIns) is JavaArrayAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(firstArgument.getElements())
is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(listOf(firstArgument), c.module.builtIns) is JavaEnumValueAnnotationArgument -> JavaAnnotationTargetMapper.mapJavaTargetArguments(listOf(firstArgument))
else -> null else -> null
} }
targetArgument?.let { mapOf(JavaAnnotationMapper.TARGET_ANNOTATION_ALLOWED_TARGETS to it) }.orEmpty() targetArgument?.let { mapOf(JavaAnnotationMapper.TARGET_ANNOTATION_ALLOWED_TARGETS to it) }.orEmpty()
@@ -137,7 +137,7 @@ class JavaRetentionAnnotationDescriptor(
c: LazyJavaResolverContext c: LazyJavaResolverContext
): JavaAnnotationDescriptor(c, annotation, KotlinBuiltIns.FQ_NAMES.retention) { ): JavaAnnotationDescriptor(c, annotation, KotlinBuiltIns.FQ_NAMES.retention) {
override val allValueArguments by c.storageManager.createLazyValue { 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() 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() 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 // Map arguments: java.lang.annotation.Target -> kotlin.annotation.Target
val kotlinTargets = arguments.filterIsInstance<JavaEnumValueAnnotationArgument>() val kotlinTargets = arguments.filterIsInstance<JavaEnumValueAnnotationArgument>()
.flatMap { mapJavaTargetArgumentByName(it.entryName?.asString()) } .flatMap { mapJavaTargetArgumentByName(it.entryName?.asString()) }
.mapNotNull { builtIns.getAnnotationTargetEnumEntry(it) } .map { kotlinTarget ->
.map(::EnumValue) EnumValue(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.annotationTarget), Name.identifier(kotlinTarget.name))
val parameterDescriptor = DescriptorResolverUtils.getAnnotationParameterByName( }
JavaAnnotationMapper.TARGET_ANNOTATION_ALLOWED_TARGETS, return ArrayValue(kotlinTargets) { module ->
builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.target) val parameterDescriptor = DescriptorResolverUtils.getAnnotationParameterByName(
) JavaAnnotationMapper.TARGET_ANNOTATION_ALLOWED_TARGETS,
return ArrayValue(kotlinTargets) { parameterDescriptor?.type ?: ErrorUtils.createErrorType("Error: AnnotationTarget[]") } module.builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.target)
)
parameterDescriptor?.type ?: ErrorUtils.createErrorType("Error: AnnotationTarget[]")
}
} }
private val retentionNameList = mapOf( private val retentionNameList = mapOf(
@@ -178,11 +181,11 @@ object JavaAnnotationTargetMapper {
"SOURCE" to KotlinRetention.SOURCE "SOURCE" to KotlinRetention.SOURCE
) )
internal fun mapJavaRetentionArgument(element: JavaAnnotationArgument?, builtIns: KotlinBuiltIns): ConstantValue<*>? { internal fun mapJavaRetentionArgument(element: JavaAnnotationArgument?): ConstantValue<*>? {
// Map argument: java.lang.annotation.Retention -> kotlin.annotation.annotation // Map argument: java.lang.annotation.Retention -> kotlin.annotation.Retention
return (element as? JavaEnumValueAnnotationArgument)?.let { return (element as? JavaEnumValueAnnotationArgument)?.let {
retentionNameList[it.entryName?.asString()]?.let { retentionNameList[it.entryName?.asString()]?.let { retention ->
builtIns.getAnnotationRetentionEnumEntry(it)?.let(::EnumValue) EnumValue(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.annotationRetention), Name.identifier(retention.name))
} }
} }
} }
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.load.java.lazy.descriptors 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.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.findNonGenericClassAcrossDependencies 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.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory 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.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.storage.getValue
@@ -98,21 +98,9 @@ class LazyJavaAnnotationDescriptor(
} }
private fun resolveFromEnumValue(enumClassId: ClassId?, entryName: Name?): ConstantValue<*>? { private fun resolveFromEnumValue(enumClassId: ClassId?, entryName: Name?): ConstantValue<*>? {
if (entryName == null) return null if (enumClassId == null || entryName == null) return null
if (enumClassId == null) { return EnumValue(enumClassId, entryName)
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)
} }
private fun resolveFromJavaClassObjectType(javaType: JavaType): ConstantValue<*>? { private fun resolveFromJavaClassObjectType(javaType: JavaType): ConstantValue<*>? {
@@ -50,11 +50,11 @@ class SignatureEnhancement(
) { ) {
private fun AnnotationDescriptor.extractNullabilityTypeFromArgument(): NullabilityQualifierWithMigrationStatus? { private fun AnnotationDescriptor.extractNullabilityTypeFromArgument(): NullabilityQualifierWithMigrationStatus? {
val enumEntryDescriptor = firstArgument().safeAs<EnumValue>()?.value val enumValue = firstArgument() as? EnumValue
// if no argument is specified, use default value: NOT_NULL // if no argument is specified, use default value: NOT_NULL
?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL) ?: return NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
return when (enumEntryDescriptor.name.asString()) { return when (enumValue.enumEntryName.asString()) {
"ALWAYS" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL) "ALWAYS" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL)
"MAYBE", "NEVER" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE) "MAYBE", "NEVER" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NULLABLE)
"UNKNOWN" -> NullabilityQualifierWithMigrationStatus(NullabilityQualifier.FORCE_FLEXIBILITY) "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.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget 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.java.components.DescriptorResolverUtils
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor
import org.jetbrains.kotlin.name.ClassId 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.AnnotationValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory 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.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer
import org.jetbrains.kotlin.serialization.deserialization.NameResolver import org.jetbrains.kotlin.serialization.deserialization.NameResolver
@@ -97,7 +97,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
} }
override fun visitEnum(name: Name, enumClassId: ClassId, enumEntryName: Name) { 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? { override fun visitArray(name: Name): AnnotationArrayArgumentVisitor? {
@@ -109,7 +109,7 @@ class BinaryClassAnnotationAndConstantLoaderImpl(
} }
override fun visitEnum(enumClassId: ClassId, enumEntryName: Name) { override fun visitEnum(enumClassId: ClassId, enumEntryName: Name) {
elements.add(enumEntryValue(enumClassId, enumEntryName)) elements.add(EnumValue(enumClassId, enumEntryName))
} }
override fun visitEnd() { 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() { override fun visitEnd() {
result.add(AnnotationDescriptorImpl(annotationClass.defaultType, arguments, source)) result.add(AnnotationDescriptorImpl(annotationClass.defaultType, arguments, source))
} }
@@ -26,8 +26,6 @@ import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget; import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention;
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget;
import org.jetbrains.kotlin.descriptors.deserialization.AdditionalClassPartsProvider; import org.jetbrains.kotlin.descriptors.deserialization.AdditionalClassPartsProvider;
import org.jetbrains.kotlin.descriptors.deserialization.ClassDescriptorFactory; import org.jetbrains.kotlin.descriptors.deserialization.ClassDescriptorFactory;
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter; import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter;
@@ -574,29 +572,6 @@ public abstract class KotlinBuiltIns {
return getBuiltInClassByName("Throwable"); return getBuiltInClassByName("Throwable");
} }
@Nullable
private static ClassDescriptor getEnumEntry(@NotNull ClassDescriptor enumDescriptor, @NotNull String entryName) {
ClassifierDescriptor result = enumDescriptor.getUnsubstitutedInnerClassesScope().getContributedClassifier(
Name.identifier(entryName), NoLookupLocation.FROM_BUILTINS
);
return result instanceof ClassDescriptor ? (ClassDescriptor) result : null;
}
@Nullable
public ClassDescriptor getDeprecationLevelEnumEntry(@NotNull String level) {
return getEnumEntry(getBuiltInClassByName(FQ_NAMES.deprecationLevel.shortName()), level);
}
@Nullable
public ClassDescriptor getAnnotationTargetEnumEntry(@NotNull KotlinTarget target) {
return getEnumEntry(getAnnotationClassByName(FQ_NAMES.annotationTarget.shortName()), target.name());
}
@Nullable
public ClassDescriptor getAnnotationRetentionEnumEntry(@NotNull KotlinRetention retention) {
return getEnumEntry(getAnnotationClassByName(FQ_NAMES.annotationRetention.shortName()), retention.name());
}
@NotNull @NotNull
public ClassDescriptor getString() { public ClassDescriptor getString() {
return getBuiltInClassByName("String"); return getBuiltInClassByName("String");
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -52,7 +53,10 @@ fun KotlinBuiltIns.createDeprecatedAnnotation(
mapOf( mapOf(
DEPRECATED_MESSAGE_NAME to StringValue(message), DEPRECATED_MESSAGE_NAME to StringValue(message),
DEPRECATED_REPLACE_WITH_NAME to AnnotationValue(replaceWithAnnotation), DEPRECATED_REPLACE_WITH_NAME to AnnotationValue(replaceWithAnnotation),
DEPRECATED_LEVEL_NAME to EnumValue(getDeprecationLevelEnumEntry(level) ?: error("Deprecation level $level not found")) DEPRECATED_LEVEL_NAME to EnumValue(
ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.deprecationLevel),
Name.identifier(level)
)
) )
) )
} }
@@ -45,6 +45,8 @@ import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
private val RETENTION_PARAMETER_NAME = Name.identifier("value")
fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor = companionObjectDescriptor ?: this fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor = companionObjectDescriptor ?: this
fun DeclarationDescriptor.getImportableDescriptor(): DeclarationDescriptor { fun DeclarationDescriptor.getImportableDescriptor(): DeclarationDescriptor {
@@ -216,11 +218,10 @@ fun Annotated.isDocumentedAnnotation(): Boolean =
annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.mustBeDocumented) != null annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.mustBeDocumented) != null
fun Annotated.getAnnotationRetention(): KotlinRetention? { fun Annotated.getAnnotationRetention(): KotlinRetention? {
val retentionArgumentValue = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.retention) val retentionArgumentValue =
?.allValueArguments annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.retention)?.allValueArguments?.get(RETENTION_PARAMETER_NAME)
?.get(Name.identifier("value")) as? EnumValue ?: return null
as? EnumValue ?: return null return KotlinRetention.valueOf(retentionArgumentValue.enumEntryName.asString())
return KotlinRetention.valueOf(retentionArgumentValue.value.name.asString())
} }
val DeclarationDescriptor.parentsWithSelf: Sequence<DeclarationDescriptor> val DeclarationDescriptor.parentsWithSelf: Sequence<DeclarationDescriptor>
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.resolve.constants
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -47,8 +46,6 @@ object ConstantValueFactory {
fun createNullValue() = NullValue() fun createNullValue() = NullValue()
fun createEnumValue(enumEntryClass: ClassDescriptor): EnumValue = EnumValue(enumEntryClass)
fun createArrayValue(value: List<ConstantValue<*>>, type: KotlinType) = createArrayValue(value) { type } fun createArrayValue(value: List<ConstantValue<*>>, type: KotlinType) = createArrayValue(value) { type }
fun createAnnotationValue(value: AnnotationDescriptor) = AnnotationValue(value) fun createAnnotationValue(value: AnnotationDescriptor) = AnnotationValue(value)
@@ -17,15 +17,13 @@
package org.jetbrains.kotlin.resolve.constants package org.jetbrains.kotlin.resolve.constants
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
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.descriptorUtil.classId import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -111,14 +109,10 @@ class DoubleValue(value: Double) : ConstantValue<Double>(value) {
override fun toString() = "$value.toDouble()" override fun toString() = "$value.toDouble()"
} }
class EnumValue(value: ClassDescriptor) : ConstantValue<ClassDescriptor>(value) { class EnumValue(val enumClassId: ClassId, val enumEntryName: Name) : ConstantValue<Pair<ClassId, Name>>(enumClassId to enumEntryName) {
val enumClassId: ClassId get() = (value.containingDeclaration as ClassDescriptor).classId!!
val enumEntryName: Name get() = value.name
override fun getType(module: ModuleDescriptor): KotlinType = override fun getType(module: ModuleDescriptor): KotlinType =
value.classValueType module.findClassAcrossModuleDependencies(enumClassId)?.takeIf(DescriptorUtils::isEnumClass)?.defaultType
?: ErrorUtils.createErrorType("Containing class for error-class based enum entry ${value.fqNameUnsafe}") ?: ErrorUtils.createErrorType("Containing class for error-class based enum entry $enumClassId.$enumEntryName")
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitEnumValue(this, data) override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitEnumValue(this, data)
@@ -368,11 +368,6 @@ public class ErrorUtils {
return new ErrorClassDescriptor(Name.special("<ERROR CLASS: " + debugMessage + ">")); return new ErrorClassDescriptor(Name.special("<ERROR CLASS: " + debugMessage + ">"));
} }
@NotNull
public static ClassDescriptor createErrorClassWithExactName(@NotNull Name name) {
return new ErrorClassDescriptor(name);
}
@NotNull @NotNull
public static MemberScope createErrorScope(@NotNull String debugMessage) { public static MemberScope createErrorScope(@NotNull String debugMessage) {
return createErrorScope(debugMessage, false); return createErrorScope(debugMessage, false);
@@ -21,13 +21,13 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
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.DescriptorUtils
import org.jetbrains.kotlin.resolve.constants.AnnotationValue import org.jetbrains.kotlin.resolve.constants.AnnotationValue
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory
import org.jetbrains.kotlin.resolve.constants.EnumValue
import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation
import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument
import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument.Value import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument.Value
@@ -85,7 +85,7 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
resolveClassLiteralValue(nameResolver.getClassId(value.classId)) resolveClassLiteralValue(nameResolver.getClassId(value.classId))
} }
Type.ENUM -> { Type.ENUM -> {
resolveEnumValue(nameResolver.getClassId(value.classId), nameResolver.getName(value.enumValueId)) EnumValue(nameResolver.getClassId(value.classId), nameResolver.getName(value.enumValueId))
} }
Type.ANNOTATION -> { Type.ANNOTATION -> {
AnnotationValue(deserializeAnnotation(value.annotation, nameResolver)) AnnotationValue(deserializeAnnotation(value.annotation, nameResolver))
@@ -137,18 +137,6 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
return ConstantValueFactory.createKClassValue(type) return ConstantValueFactory.createKClassValue(type)
} }
// NOTE: see analogous code in BinaryClassAnnotationAndConstantLoaderImpl
private fun resolveEnumValue(enumClassId: ClassId, enumEntryName: Name): ConstantValue<*> {
val enumClass = resolveClass(enumClassId)
if (enumClass.kind == ClassKind.ENUM_CLASS) {
val enumEntry = enumClass.unsubstitutedInnerClassesScope.getContributedClassifier(enumEntryName, NoLookupLocation.FROM_DESERIALIZATION)
if (enumEntry is ClassDescriptor) {
return ConstantValueFactory.createEnumValue(enumEntry)
}
}
return ConstantValueFactory.createErrorValue("Unresolved enum entry: $enumClassId.$enumEntryName")
}
private fun resolveArrayElementType(value: Value, nameResolver: NameResolver): SimpleType = private fun resolveArrayElementType(value: Value, nameResolver: NameResolver): SimpleType =
with(builtIns) { with(builtIns) {
when (value.type) { when (value.type) {
@@ -197,7 +197,7 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans
): Pair<List<EntryWithConstants>, Int> { ): Pair<List<EntryWithConstants>, Int> {
return collectConstantEntries( return collectConstantEntries(
fromIndex, entries, fromIndex, entries,
{ (it.toConstantValue(expectedType) as? EnumValue)?.value?.name?.identifier }, { (it.toConstantValue(expectedType) as? EnumValue)?.enumEntryName?.identifier },
{ uniqueEnumNames.add(it) }, { uniqueEnumNames.add(it) },
{ JsStringLiteral(it) } { JsStringLiteral(it) }
) )
@@ -17,7 +17,8 @@
package org.jetbrains.kotlin.android.synthetic.descriptors package org.jetbrains.kotlin.android.synthetic.descriptors
import kotlinx.android.extensions.CacheImplementation import kotlinx.android.extensions.CacheImplementation
import kotlinx.android.extensions.CacheImplementation.* import kotlinx.android.extensions.CacheImplementation.NO_CACHE
import kotlinx.android.extensions.CacheImplementation.valueOf
import kotlinx.android.extensions.ContainerOptions import kotlinx.android.extensions.ContainerOptions
import org.jetbrains.kotlin.android.synthetic.codegen.AndroidContainerType import org.jetbrains.kotlin.android.synthetic.codegen.AndroidContainerType
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -61,7 +62,7 @@ class ContainerOptionsProxy(val containerType: AndroidContainerType, val cache:
} }
private fun <E : Enum<E>> AnnotationDescriptor.getEnumValue(name: String, factory: (String) -> E): E? { private fun <E : Enum<E>> AnnotationDescriptor.getEnumValue(name: String, factory: (String) -> E): E? {
val valueName = (allValueArguments[Name.identifier(name)] as? EnumValue)?.value?.name?.asString() ?: return null val valueName = (allValueArguments[Name.identifier(name)] as? EnumValue)?.enumEntryName?.asString() ?: return null
return try { return try {
factory(valueName) factory(valueName)
@@ -70,4 +71,4 @@ private fun <E : Enum<E>> AnnotationDescriptor.getEnumValue(name: String, factor
// Enum.valueOf() may throw this // Enum.valueOf() may throw this
null null
} }
} }