Value classes: Allow unsigned arrays in annotations
including varargs, apparently. So, we allow unsigned types and unsigned arrays in annotations, but disallow user-defined inline classes. #KT-23816 Fixed
This commit is contained in:
@@ -153,6 +153,10 @@ object StandardNames {
|
||||
@JvmField val uShort: ClassId = ClassId.topLevel(uShortFqName)
|
||||
@JvmField val uInt: ClassId = ClassId.topLevel(uIntFqName)
|
||||
@JvmField val uLong: ClassId = ClassId.topLevel(uLongFqName)
|
||||
@JvmField val uByteArrayFqName: FqName = fqName("UByteArray")
|
||||
@JvmField val uShortArrayFqName: FqName = fqName("UShortArray")
|
||||
@JvmField val uIntArrayFqName: FqName = fqName("UIntArray")
|
||||
@JvmField val uLongArrayFqName: FqName = fqName("ULongArray")
|
||||
|
||||
@JvmField val primitiveTypeShortNames: Set<Name> = newHashSetWithExpectedSize<Name>(PrimitiveType.values().size).apply {
|
||||
PrimitiveType.values().mapTo(this) { it.typeName }
|
||||
|
||||
@@ -819,6 +819,26 @@ public abstract class KotlinBuiltIns {
|
||||
return isConstructedFromGivenClassAndNotNullable(type, FqNames.uLongFqName.toUnsafe());
|
||||
}
|
||||
|
||||
public static boolean isUByteArray(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClassAndNotNullable(type, FqNames.uByteArrayFqName.toUnsafe());
|
||||
}
|
||||
|
||||
public static boolean isUShortArray(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClassAndNotNullable(type, FqNames.uShortArrayFqName.toUnsafe());
|
||||
}
|
||||
|
||||
public static boolean isUIntArray(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClassAndNotNullable(type, FqNames.uIntArrayFqName.toUnsafe());
|
||||
}
|
||||
|
||||
public static boolean isULongArray(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClassAndNotNullable(type, FqNames.uLongArrayFqName.toUnsafe());
|
||||
}
|
||||
|
||||
public static boolean isUnsignedArrayType(@NotNull KotlinType type) {
|
||||
return isUByteArray(type) || isUShortArray(type) || isUIntArray(type) || isULongArray(type);
|
||||
}
|
||||
|
||||
public static boolean isDoubleOrNullableDouble(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClass(type, FqNames._double);
|
||||
}
|
||||
|
||||
@@ -23,10 +23,26 @@ enum class UnsignedType(val classId: ClassId) {
|
||||
val arrayClassId = ClassId(classId.packageFqName, Name.identifier(typeName.asString() + "Array"))
|
||||
}
|
||||
|
||||
enum class UnsignedArrayType(val classId: ClassId) {
|
||||
UBYTEARRAY(ClassId.fromString("kotlin/UByteArray")),
|
||||
USHORTARRAY(ClassId.fromString("kotlin/UShortArray")),
|
||||
UINTARRAY(ClassId.fromString("kotlin/UIntArray")),
|
||||
ULONGARRAY(ClassId.fromString("kotlin/ULongArray"));
|
||||
|
||||
val typeName = classId.shortClassName
|
||||
}
|
||||
|
||||
object UnsignedTypes {
|
||||
private val unsignedTypeNames = enumValues<UnsignedType>().map { it.typeName }.toSet()
|
||||
private val unsignedArrayTypeNames = enumValues<UnsignedArrayType>().map { it.typeName }.toSet()
|
||||
private val arrayClassIdToUnsignedClassId = hashMapOf<ClassId, ClassId>()
|
||||
private val unsignedClassIdToArrayClassId = hashMapOf<ClassId, ClassId>()
|
||||
val unsignedArrayTypeToArrayCall = hashMapOf(
|
||||
UnsignedArrayType.UBYTEARRAY to Name.identifier("ubyteArrayOf"),
|
||||
UnsignedArrayType.USHORTARRAY to Name.identifier("ushortArrayOf"),
|
||||
UnsignedArrayType.UINTARRAY to Name.identifier("uintArrayOf"),
|
||||
UnsignedArrayType.ULONGARRAY to Name.identifier("ulongArrayOf"),
|
||||
)
|
||||
|
||||
private val arrayClassesShortNames: Set<Name> = UnsignedType.values().mapTo(mutableSetOf()) { it.arrayClassId.shortClassName }
|
||||
|
||||
@@ -66,4 +82,40 @@ object UnsignedTypes {
|
||||
container.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME &&
|
||||
descriptor.name in UnsignedTypes.unsignedTypeNames
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isUnsignedArrayType(type: KotlinType): Boolean {
|
||||
if (TypeUtils.noExpectedType(type)) return false
|
||||
|
||||
val descriptor = type.constructor.declarationDescriptor ?: return false
|
||||
return isUnsignedArrayClass(descriptor)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun toUnsignedArrayType(type: KotlinType): UnsignedArrayType? =
|
||||
when {
|
||||
KotlinBuiltIns.isUByteArray(type) -> UnsignedArrayType.UBYTEARRAY
|
||||
KotlinBuiltIns.isUShortArray(type) -> UnsignedArrayType.USHORTARRAY
|
||||
KotlinBuiltIns.isUIntArray(type) -> UnsignedArrayType.UINTARRAY
|
||||
KotlinBuiltIns.isULongArray(type) -> UnsignedArrayType.ULONGARRAY
|
||||
else -> null
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun toUnsignedArrayType(descriptor: DeclarationDescriptor): UnsignedArrayType? =
|
||||
if (!isUnsignedArrayClass(descriptor)) null
|
||||
else when (descriptor.name.asString()) {
|
||||
"UByteArray" -> UnsignedArrayType.UBYTEARRAY
|
||||
"UShortArray" -> UnsignedArrayType.USHORTARRAY
|
||||
"UIntArray" -> UnsignedArrayType.UINTARRAY
|
||||
"ULongArray" -> UnsignedArrayType.ULONGARRAY
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun isUnsignedArrayClass(descriptor: DeclarationDescriptor): Boolean {
|
||||
val container = descriptor.containingDeclaration
|
||||
return container is PackageFragmentDescriptor &&
|
||||
container.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME &&
|
||||
descriptor.name in unsignedArrayTypeNames
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,11 +56,13 @@ class AnnotationValue(value: AnnotationDescriptor) : ConstantValue<AnnotationDes
|
||||
}
|
||||
|
||||
class ArrayValue(
|
||||
value: List<ConstantValue<*>>,
|
||||
private val computeType: (ModuleDescriptor) -> KotlinType
|
||||
value: List<ConstantValue<*>>,
|
||||
private val computeType: (ModuleDescriptor) -> KotlinType
|
||||
) : ConstantValue<List<ConstantValue<*>>>(value) {
|
||||
override fun getType(module: ModuleDescriptor): KotlinType = computeType(module).also { type ->
|
||||
assert(KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type)) { "Type should be an array, but was $type: $value" }
|
||||
assert(KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type) || KotlinBuiltIns.isUnsignedArrayType(type)) {
|
||||
"Type should be an array, but was $type: $value"
|
||||
}
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitArrayValue(this, data)
|
||||
|
||||
Reference in New Issue
Block a user