Restore support for local class literals in annotation arguments
This was broken in c1ab08c8ce where we started to represent KClassValue
as a ClassId of the referenced class + number of times it's been wrapped
into kotlin.Array. Local classes do not have a sane ClassId, so in this
change we restore the old behavior by representing KClassValue with a
sealed class value instead
#KT-29891 Fixed
This commit is contained in:
@@ -462,10 +462,13 @@ internal class DescriptorRendererImpl(
|
||||
return when (value) {
|
||||
is ArrayValue -> value.value.joinToString(", ", "{", "}") { renderConstant(it) }
|
||||
is AnnotationValue -> renderAnnotation(value.value).removePrefix("@")
|
||||
is KClassValue -> {
|
||||
var type = value.classId.asSingleFqName().asString()
|
||||
repeat(value.arrayDimensions) { type = "kotlin.Array<$type>" }
|
||||
"$type::class"
|
||||
is KClassValue -> when (val classValue = value.value) {
|
||||
is KClassValue.Value.LocalClass -> "${classValue.type}::class"
|
||||
is KClassValue.Value.NormalClass -> {
|
||||
var type = classValue.classId.asSingleFqName().asString()
|
||||
repeat(classValue.arrayDimensions) { type = "kotlin.Array<$type>" }
|
||||
"$type::class"
|
||||
}
|
||||
}
|
||||
else -> value.toString()
|
||||
}
|
||||
|
||||
@@ -158,9 +158,17 @@ class IntValue(value: Int) : IntegerValueConstant<Int>(value) {
|
||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitIntValue(this, data)
|
||||
}
|
||||
|
||||
class KClassValue(value: ClassLiteralValue) : ConstantValue<ClassLiteralValue>(value) {
|
||||
val classId: ClassId get() = value.classId
|
||||
val arrayDimensions: Int get() = value.arrayNestedness
|
||||
class KClassValue(value: Value) : ConstantValue<KClassValue.Value>(value) {
|
||||
sealed class Value {
|
||||
data class NormalClass(val value: ClassLiteralValue) : Value() {
|
||||
val classId: ClassId get() = value.classId
|
||||
val arrayDimensions: Int get() = value.arrayNestedness
|
||||
}
|
||||
|
||||
data class LocalClass(val type: KotlinType) : Value()
|
||||
}
|
||||
|
||||
constructor(value: ClassLiteralValue) : this(Value.NormalClass(value))
|
||||
|
||||
constructor(classId: ClassId, arrayDimensions: Int) : this(ClassLiteralValue(classId, arrayDimensions))
|
||||
|
||||
@@ -168,17 +176,23 @@ class KClassValue(value: ClassLiteralValue) : ConstantValue<ClassLiteralValue>(v
|
||||
KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, module.builtIns.kClass, listOf(TypeProjectionImpl(getArgumentType(module))))
|
||||
|
||||
fun getArgumentType(module: ModuleDescriptor): KotlinType {
|
||||
val descriptor = module.findClassAcrossModuleDependencies(classId)
|
||||
?: return ErrorUtils.createErrorType("Unresolved type: $classId (arrayDimensions=$arrayDimensions)")
|
||||
when (value) {
|
||||
is Value.LocalClass -> return value.type
|
||||
is Value.NormalClass -> {
|
||||
val (classId, arrayDimensions) = value.value
|
||||
val descriptor = module.findClassAcrossModuleDependencies(classId)
|
||||
?: return ErrorUtils.createErrorType("Unresolved type: $classId (arrayDimensions=$arrayDimensions)")
|
||||
|
||||
// If this value refers to a class named test.Foo.Bar where both Foo and Bar have generic type parameters,
|
||||
// we're constructing a type `test.Foo<*>.Bar<*>` below
|
||||
var type = descriptor.defaultType.replaceArgumentsWithStarProjections()
|
||||
repeat(arrayDimensions) {
|
||||
type = module.builtIns.getArrayType(Variance.INVARIANT, type)
|
||||
// If this value refers to a class named test.Foo.Bar where both Foo and Bar have generic type parameters,
|
||||
// we're constructing a type `test.Foo<*>.Bar<*>` below
|
||||
var type = descriptor.defaultType.replaceArgumentsWithStarProjections()
|
||||
repeat(arrayDimensions) {
|
||||
type = module.builtIns.getArrayType(Variance.INVARIANT, type)
|
||||
}
|
||||
|
||||
return type
|
||||
}
|
||||
}
|
||||
|
||||
return type
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitKClassValue(this, data)
|
||||
@@ -196,7 +210,7 @@ class KClassValue(value: ClassLiteralValue) : ConstantValue<ClassLiteralValue>(v
|
||||
|
||||
return when (val descriptor = type.constructor.declarationDescriptor) {
|
||||
is ClassDescriptor -> {
|
||||
val classId = descriptor.classId ?: return null
|
||||
val classId = descriptor.classId ?: return KClassValue(KClassValue.Value.LocalClass(argumentType))
|
||||
KClassValue(classId, arrayDimensions)
|
||||
}
|
||||
is TypeParameterDescriptor -> {
|
||||
|
||||
@@ -140,9 +140,13 @@ private fun ConstantValue<*>.toRuntimeValue(classLoader: ClassLoader): Any? = wh
|
||||
Util.getEnumConstantByName(enumClass as Class<out Enum<*>>, entryName.asString())
|
||||
}
|
||||
}
|
||||
is KClassValue -> {
|
||||
val (classId, arrayDimensions) = value
|
||||
loadClass(classLoader, classId, arrayDimensions)
|
||||
is KClassValue -> when (val classValue = value) {
|
||||
is KClassValue.Value.NormalClass ->
|
||||
loadClass(classLoader, classValue.classId, classValue.arrayDimensions)
|
||||
is KClassValue.Value.LocalClass -> {
|
||||
// TODO: this doesn't work because of KT-30013
|
||||
(classValue.type.constructor.declarationDescriptor as? ClassDescriptor)?.toJavaClass()
|
||||
}
|
||||
}
|
||||
is ErrorValue, is NullValue -> null
|
||||
else -> value // Primitives and strings
|
||||
|
||||
Reference in New Issue
Block a user