Write is_unsigned flag into metadata for an annotation arguments

Instead of adding new kind of types, we'll use flag to disambiguate
 usual types from unsigned ones, this approach has two advantages:
 - less changes in the metadata format
 - it allows naturally extend format for unsigned arrays,
  which will be supported later

 #KT-25310 Fixed
 #KT-25273 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2018-07-06 01:41:13 +03:00
parent 8c075bc622
commit 0c6757a8b0
13 changed files with 487 additions and 169 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument.Value
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument.Value.Type
import org.jetbrains.kotlin.metadata.deserialization.Flags
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -67,12 +68,14 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
value: Value,
nameResolver: NameResolver
): ConstantValue<*> {
val isUnsigned = Flags.IS_UNSIGNED.get(value.flags)
val result: ConstantValue<*> = when (value.type) {
Type.BYTE -> ByteValue(value.intValue.toByte())
Type.BYTE -> value.intValue.toByte().letIf(isUnsigned, ::UByteValue, ::ByteValue)
Type.CHAR -> CharValue(value.intValue.toChar())
Type.SHORT -> ShortValue(value.intValue.toShort())
Type.INT -> IntValue(value.intValue.toInt())
Type.LONG -> LongValue(value.intValue)
Type.SHORT -> value.intValue.toShort().letIf(isUnsigned, ::UShortValue, ::ShortValue)
Type.INT -> value.intValue.toInt().letIf(isUnsigned, ::UIntValue, ::IntValue)
Type.LONG -> value.intValue.letIf(isUnsigned, ::ULongValue, ::LongValue)
Type.FLOAT -> FloatValue(value.floatValue)
Type.DOUBLE -> DoubleValue(value.doubleValue)
Type.BOOLEAN -> BooleanValue(value.intValue != 0L)
@@ -126,6 +129,9 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
}
}
private inline fun <T, R> T.letIf(predicate: Boolean, f: (T) -> R, g: (T) -> R): R =
if (predicate) f(this) else g(this)
private fun resolveClassLiteralValue(classId: ClassId): ConstantValue<*> {
// If value refers to a class named test.Foo.Bar where both Foo and Bar have generic type parameters,
// we're constructing a type `KClass<test.Foo<*>.Bar<*>>` below