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:
@@ -438,7 +438,7 @@ public abstract class AnnotationCodegen {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Set<ElementType> getJavaTargetList(ClassDescriptor descriptor) {
|
||||
private static Set<ElementType> getJavaTargetList(ClassDescriptor descriptor) {
|
||||
AnnotationDescriptor targetAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Target.class.getName()));
|
||||
if (targetAnnotation != null) {
|
||||
Collection<ConstantValue<?>> valueArguments = targetAnnotation.getAllValueArguments().values();
|
||||
@@ -449,12 +449,9 @@ public abstract class AnnotationCodegen {
|
||||
Set<ElementType> result = EnumSet.noneOf(ElementType.class);
|
||||
for (ConstantValue<?> value : values) {
|
||||
if (value instanceof EnumValue) {
|
||||
ClassDescriptor enumEntry = ((EnumValue) value).getValue();
|
||||
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
|
||||
if (classObjectType != null) {
|
||||
if ("java/lang/annotation/ElementType".equals(typeMapper.mapType(classObjectType).getInternalName())) {
|
||||
result.add(ElementType.valueOf(enumEntry.getName().asString()));
|
||||
}
|
||||
FqName enumClassFqName = ((EnumValue) value).getEnumClassId().asSingleFqName();
|
||||
if (ElementType.class.getName().equals(enumClassFqName.asString())) {
|
||||
result.add(ElementType.valueOf(((EnumValue) value).getEnumEntryName().asString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -466,21 +463,18 @@ public abstract class AnnotationCodegen {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) {
|
||||
private static RetentionPolicy getRetentionPolicy(@NotNull Annotated descriptor) {
|
||||
KotlinRetention retention = DescriptorUtilsKt.getAnnotationRetention(descriptor);
|
||||
if (retention != null) {
|
||||
return annotationRetentionMap.get(retention);
|
||||
}
|
||||
AnnotationDescriptor retentionAnnotation = descriptor.getAnnotations().findAnnotation(new FqName(Retention.class.getName()));
|
||||
if (retentionAnnotation != null) {
|
||||
ConstantValue<?> compileTimeConstant = CollectionsKt.firstOrNull(retentionAnnotation.getAllValueArguments().values());
|
||||
if (compileTimeConstant instanceof EnumValue) {
|
||||
ClassDescriptor enumEntry = ((EnumValue) compileTimeConstant).getValue();
|
||||
KotlinType classObjectType = DescriptorUtilsKt.getClassValueType(enumEntry);
|
||||
if (classObjectType != null) {
|
||||
if ("java/lang/annotation/RetentionPolicy".equals(typeMapper.mapType(classObjectType).getInternalName())) {
|
||||
return RetentionPolicy.valueOf(enumEntry.getName().asString());
|
||||
}
|
||||
ConstantValue<?> value = CollectionsKt.firstOrNull(retentionAnnotation.getAllValueArguments().values());
|
||||
if (value instanceof EnumValue) {
|
||||
FqName enumClassFqName = ((EnumValue) value).getEnumClassId().asSingleFqName();
|
||||
if (RetentionPolicy.class.getName().equals(enumClassFqName.asString())) {
|
||||
return RetentionPolicy.valueOf(((EnumValue) value).getEnumEntryName().asString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,16 +59,18 @@ class JvmStringTable(private val typeMapper: KotlinTypeMapper) : StringTable {
|
||||
throw IllegalStateException("Cannot get FQ name of error class: " + descriptor)
|
||||
}
|
||||
|
||||
// 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
|
||||
return getClassIdIndex(descriptor.classId)
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
map[string]?.let { recordedIndex ->
|
||||
|
||||
+2
-2
@@ -108,11 +108,11 @@ public class MappingClassesForWhenByEnumCodegen {
|
||||
v.putstatic(cb.getThisName(), mapping.getFieldName(), MAPPINGS_FIELD_DESCRIPTOR);
|
||||
|
||||
for (Map.Entry<EnumValue, Integer> item : mapping.enumValuesToIntMapping()) {
|
||||
EnumValue enumEntry = item.getKey();
|
||||
EnumValue enumValue = item.getKey();
|
||||
int mappedValue = item.getValue();
|
||||
|
||||
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.iconst(mappedValue);
|
||||
v.astore(Type.INT_TYPE);
|
||||
|
||||
@@ -208,7 +208,7 @@ class AnnotationChecker(
|
||||
val valueArguments = targetEntryDescriptor.allValueArguments
|
||||
val valueArgument = valueArguments.entries.firstOrNull()?.value as? ArrayValue ?: return null
|
||||
return valueArgument.value.filterIsInstance<EnumValue>().mapNotNull {
|
||||
KotlinTarget.valueOrNull(it.value.name.asString())
|
||||
KotlinTarget.valueOrNull(it.enumEntryName.asString())
|
||||
}.toSet()
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -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.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
@@ -662,7 +663,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||
val enumDescriptor = trace.bindingContext.get(BindingContext.REFERENCE_TARGET, expression)
|
||||
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)
|
||||
|
||||
+2
-3
@@ -78,9 +78,8 @@ class AnnotationSerializer(private val stringTable: StringTable) {
|
||||
|
||||
override fun visitEnumValue(value: EnumValue, data: Unit) {
|
||||
type = Type.ENUM
|
||||
val enumEntry = value.value
|
||||
classId = stringTable.getFqNameIndex(enumEntry.containingDeclaration as ClassDescriptor)
|
||||
enumValueId = stringTable.getStringIndex(enumEntry.name.asString())
|
||||
classId = stringTable.getClassIdIndex(value.enumClassId)
|
||||
enumValueId = stringTable.getStringIndex(value.enumEntryName.asString())
|
||||
}
|
||||
|
||||
override fun visitErrorValue(value: ErrorValue, data: Unit) {
|
||||
|
||||
+8
-8
@@ -644,19 +644,19 @@ class DescriptorSerializer private constructor(
|
||||
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) {
|
||||
DeprecationLevel.ERROR.toString() -> { /* ERROR is the default level */ }
|
||||
DeprecationLevel.WARNING.toString() -> proto.level = ProtoBuf.VersionRequirement.Level.WARNING
|
||||
DeprecationLevel.HIDDEN.toString() -> proto.level = ProtoBuf.VersionRequirement.Level.HIDDEN
|
||||
DeprecationLevel.ERROR.name -> { /* ERROR is the default level */ }
|
||||
DeprecationLevel.WARNING.name -> proto.level = ProtoBuf.VersionRequirement.Level.WARNING
|
||||
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) {
|
||||
ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION.toString() -> { /* LANGUAGE_VERSION is the default kind */ }
|
||||
ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION.toString() ->
|
||||
ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION.name -> { /* LANGUAGE_VERSION is the default kind */ }
|
||||
ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION.name ->
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.serialization
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import java.io.OutputStream
|
||||
|
||||
interface StringTable {
|
||||
@@ -24,5 +25,7 @@ interface StringTable {
|
||||
|
||||
fun getFqNameIndex(descriptor: ClassifierDescriptorWithTypeParameters): Int
|
||||
|
||||
fun getClassIdIndex(classId: ClassId): Int
|
||||
|
||||
fun serializeTo(output: OutputStream)
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ open class StringTableImpl : StringTable {
|
||||
return getClassIdIndex(classId)
|
||||
}
|
||||
|
||||
fun getClassIdIndex(classId: ClassId): Int {
|
||||
override fun getClassIdIndex(classId: ClassId): Int {
|
||||
val builder = QualifiedName.newBuilder()
|
||||
builder.kind = QualifiedName.Kind.CLASS
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ public final annotation class Anno : kotlin.Annotation {
|
||||
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()
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -169,8 +169,7 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() {
|
||||
it.allValueArguments.forEach {
|
||||
val argument = it.value
|
||||
if (argument is EnumValue) {
|
||||
Assert.assertEquals("Enum entry name should be <module-name>X", "X", argument.value.name.identifier.last().toString())
|
||||
checkDescriptor(argument.value, callable)
|
||||
Assert.assertEquals("Enum entry name should be <module-name>X", "X", argument.enumEntryName.identifier.last().toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-6
@@ -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
|
||||
|
||||
+18
-15
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-15
@@ -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<*>? {
|
||||
|
||||
+4
-4
@@ -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)
|
||||
|
||||
+3
-15
@@ -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))
|
||||
}
|
||||
|
||||
@@ -26,8 +26,6 @@ import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||
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.ClassDescriptorFactory;
|
||||
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter;
|
||||
@@ -574,29 +572,6 @@ public abstract class KotlinBuiltIns {
|
||||
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
|
||||
public ClassDescriptor getString() {
|
||||
return getBuiltInClassByName("String");
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -52,7 +53,10 @@ fun KotlinBuiltIns.createDeprecatedAnnotation(
|
||||
mapOf(
|
||||
DEPRECATED_MESSAGE_NAME to StringValue(message),
|
||||
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.addToStdlib.safeAs
|
||||
|
||||
private val RETENTION_PARAMETER_NAME = Name.identifier("value")
|
||||
|
||||
fun ClassDescriptor.getClassObjectReferenceTarget(): ClassDescriptor = companionObjectDescriptor ?: this
|
||||
|
||||
fun DeclarationDescriptor.getImportableDescriptor(): DeclarationDescriptor {
|
||||
@@ -216,11 +218,10 @@ fun Annotated.isDocumentedAnnotation(): Boolean =
|
||||
annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.mustBeDocumented) != null
|
||||
|
||||
fun Annotated.getAnnotationRetention(): KotlinRetention? {
|
||||
val retentionArgumentValue = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.retention)
|
||||
?.allValueArguments
|
||||
?.get(Name.identifier("value"))
|
||||
as? EnumValue ?: return null
|
||||
return KotlinRetention.valueOf(retentionArgumentValue.value.name.asString())
|
||||
val retentionArgumentValue =
|
||||
annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.retention)?.allValueArguments?.get(RETENTION_PARAMETER_NAME)
|
||||
as? EnumValue ?: return null
|
||||
return KotlinRetention.valueOf(retentionArgumentValue.enumEntryName.asString())
|
||||
}
|
||||
|
||||
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.PrimitiveType
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -47,8 +46,6 @@ object ConstantValueFactory {
|
||||
|
||||
fun createNullValue() = NullValue()
|
||||
|
||||
fun createEnumValue(enumEntryClass: ClassDescriptor): EnumValue = EnumValue(enumEntryClass)
|
||||
|
||||
fun createArrayValue(value: List<ConstantValue<*>>, type: KotlinType) = createArrayValue(value) { type }
|
||||
|
||||
fun createAnnotationValue(value: AnnotationDescriptor) = AnnotationValue(value)
|
||||
|
||||
@@ -17,15 +17,13 @@
|
||||
package org.jetbrains.kotlin.resolve.constants
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationArgumentVisitor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
@@ -111,14 +109,10 @@ class DoubleValue(value: Double) : ConstantValue<Double>(value) {
|
||||
override fun toString() = "$value.toDouble()"
|
||||
}
|
||||
|
||||
class EnumValue(value: ClassDescriptor) : ConstantValue<ClassDescriptor>(value) {
|
||||
val enumClassId: ClassId get() = (value.containingDeclaration as ClassDescriptor).classId!!
|
||||
|
||||
val enumEntryName: Name get() = value.name
|
||||
|
||||
class EnumValue(val enumClassId: ClassId, val enumEntryName: Name) : ConstantValue<Pair<ClassId, Name>>(enumClassId to enumEntryName) {
|
||||
override fun getType(module: ModuleDescriptor): KotlinType =
|
||||
value.classValueType
|
||||
?: ErrorUtils.createErrorType("Containing class for error-class based enum entry ${value.fqNameUnsafe}")
|
||||
module.findClassAcrossModuleDependencies(enumClassId)?.takeIf(DescriptorUtils::isEnumClass)?.defaultType
|
||||
?: 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)
|
||||
|
||||
|
||||
@@ -368,11 +368,6 @@ public class ErrorUtils {
|
||||
return new ErrorClassDescriptor(Name.special("<ERROR CLASS: " + debugMessage + ">"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor createErrorClassWithExactName(@NotNull Name name) {
|
||||
return new ErrorClassDescriptor(name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static MemberScope createErrorScope(@NotNull String debugMessage) {
|
||||
return createErrorScope(debugMessage, false);
|
||||
|
||||
+2
-14
@@ -21,13 +21,13 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||
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.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
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.Annotation
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument
|
||||
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))
|
||||
}
|
||||
Type.ENUM -> {
|
||||
resolveEnumValue(nameResolver.getClassId(value.classId), nameResolver.getName(value.enumValueId))
|
||||
EnumValue(nameResolver.getClassId(value.classId), nameResolver.getName(value.enumValueId))
|
||||
}
|
||||
Type.ANNOTATION -> {
|
||||
AnnotationValue(deserializeAnnotation(value.annotation, nameResolver))
|
||||
@@ -137,18 +137,6 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
|
||||
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 =
|
||||
with(builtIns) {
|
||||
when (value.type) {
|
||||
|
||||
@@ -197,7 +197,7 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans
|
||||
): Pair<List<EntryWithConstants>, Int> {
|
||||
return collectConstantEntries(
|
||||
fromIndex, entries,
|
||||
{ (it.toConstantValue(expectedType) as? EnumValue)?.value?.name?.identifier },
|
||||
{ (it.toConstantValue(expectedType) as? EnumValue)?.enumEntryName?.identifier },
|
||||
{ uniqueEnumNames.add(it) },
|
||||
{ JsStringLiteral(it) }
|
||||
)
|
||||
|
||||
+4
-3
@@ -17,7 +17,8 @@
|
||||
package org.jetbrains.kotlin.android.synthetic.descriptors
|
||||
|
||||
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 org.jetbrains.kotlin.android.synthetic.codegen.AndroidContainerType
|
||||
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? {
|
||||
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 {
|
||||
factory(valueName)
|
||||
@@ -70,4 +71,4 @@ private fun <E : Enum<E>> AnnotationDescriptor.getEnumValue(name: String, factor
|
||||
// Enum.valueOf() may throw this
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user