Treat number with unsigned literal as UByte & UShort & UInt & ULong
This commit is contained in:
@@ -332,6 +332,15 @@ public abstract class KotlinBuiltIns {
|
||||
public final FqNameUnsafe kMutableProperty2 = reflect("KMutableProperty2");
|
||||
public final ClassId kProperty = ClassId.topLevel(reflect("KProperty").toSafe());
|
||||
|
||||
public final FqName uByteFqName = fqName("UByte");
|
||||
public final FqName uShortFqName = fqName("UShort");
|
||||
public final FqName uIntFqName = fqName("UInt");
|
||||
public final FqName uLongFqName = fqName("ULong");
|
||||
public final ClassId uByte = ClassId.topLevel(uByteFqName);
|
||||
public final ClassId uShort = ClassId.topLevel(uShortFqName);
|
||||
public final ClassId uInt = ClassId.topLevel(uIntFqName);
|
||||
public final ClassId uLong = ClassId.topLevel(uLongFqName);
|
||||
|
||||
public final Set<Name> primitiveTypeShortNames = newHashSetWithExpectedSize(PrimitiveType.values().length);
|
||||
public final Set<Name> primitiveArrayTypeShortNames = newHashSetWithExpectedSize(PrimitiveType.values().length);
|
||||
public final Map<FqNameUnsafe, PrimitiveType> fqNameToPrimitiveType = newHashMapWithExpectedSize(PrimitiveType.values().length);
|
||||
@@ -975,6 +984,22 @@ public abstract class KotlinBuiltIns {
|
||||
return isDoubleOrNullableDouble(type) && !type.isMarkedNullable();
|
||||
}
|
||||
|
||||
public static boolean isUByte(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES.uByteFqName.toUnsafe());
|
||||
}
|
||||
|
||||
public static boolean isUShort(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES.uShortFqName.toUnsafe());
|
||||
}
|
||||
|
||||
public static boolean isUInt(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES.uIntFqName.toUnsafe());
|
||||
}
|
||||
|
||||
public static boolean isULong(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES.uLongFqName.toUnsafe());
|
||||
}
|
||||
|
||||
public static boolean isDoubleOrNullableDouble(@NotNull KotlinType type) {
|
||||
return isConstructedFromGivenClass(type, FQ_NAMES._double);
|
||||
}
|
||||
|
||||
@@ -42,9 +42,12 @@ interface CompileTimeConstant<out T> {
|
||||
|
||||
val isPure: Boolean get() = parameters.isPure
|
||||
|
||||
val isUnsigned: Boolean get() = parameters.isUnsigned
|
||||
|
||||
class Parameters(
|
||||
val canBeUsedInAnnotation: Boolean,
|
||||
val isPure: Boolean,
|
||||
val isUnsigned: Boolean,
|
||||
val usesVariableAsConstant: Boolean,
|
||||
val usesNonConstValAsConstant: Boolean
|
||||
)
|
||||
@@ -84,10 +87,10 @@ class TypedCompileTimeConstant<out T>(
|
||||
|
||||
class IntegerValueTypeConstant(
|
||||
private val value: Number,
|
||||
builtIns: KotlinBuiltIns,
|
||||
module: ModuleDescriptor,
|
||||
override val parameters: CompileTimeConstant.Parameters
|
||||
) : CompileTimeConstant<Number> {
|
||||
private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), builtIns)
|
||||
private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), module, parameters)
|
||||
|
||||
override fun toConstantValue(expectedType: KotlinType): ConstantValue<Number> {
|
||||
val type = getType(expectedType)
|
||||
@@ -95,6 +98,13 @@ class IntegerValueTypeConstant(
|
||||
KotlinBuiltIns.isInt(type) -> IntValue(value.toInt())
|
||||
KotlinBuiltIns.isByte(type) -> ByteValue(value.toByte())
|
||||
KotlinBuiltIns.isShort(type) -> ShortValue(value.toShort())
|
||||
KotlinBuiltIns.isLong(type) -> LongValue(value.toLong())
|
||||
|
||||
KotlinBuiltIns.isUInt(type) -> UIntValue(value.toInt())
|
||||
KotlinBuiltIns.isUByte(type) -> UByteValue(value.toByte())
|
||||
KotlinBuiltIns.isUShort(type) -> UShortValue(value.toShort())
|
||||
KotlinBuiltIns.isULong(type) -> ULongValue(value.toLong())
|
||||
|
||||
else -> LongValue(value.toLong())
|
||||
}
|
||||
}
|
||||
|
||||
+23
-13
@@ -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.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
@@ -51,10 +50,10 @@ object ConstantValueFactory {
|
||||
|
||||
fun createUnsignedValue(constantValue: ConstantValue<*>, type: KotlinType): UnsignedValueConstant<*>? {
|
||||
return when (constantValue) {
|
||||
is ByteValue -> UByteValue(constantValue, type)
|
||||
is ShortValue -> UShortValue(constantValue, type)
|
||||
is IntValue -> UIntValue(constantValue, type)
|
||||
is LongValue -> ULongValue(constantValue, type)
|
||||
is ByteValue -> UByteValue(constantValue.value)
|
||||
is ShortValue -> UShortValue(constantValue.value)
|
||||
is IntValue -> UIntValue(constantValue.value)
|
||||
is LongValue -> ULongValue(constantValue.value)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -66,16 +65,27 @@ object ConstantValueFactory {
|
||||
|
||||
fun createIntegerConstantValue(
|
||||
value: Long,
|
||||
expectedType: KotlinType
|
||||
expectedType: KotlinType,
|
||||
isUnsigned: Boolean
|
||||
): ConstantValue<*>? {
|
||||
val notNullExpected = TypeUtils.makeNotNullable(expectedType)
|
||||
return when {
|
||||
KotlinBuiltIns.isLong(notNullExpected) -> LongValue(value)
|
||||
KotlinBuiltIns.isInt(notNullExpected) && value == value.toInt().toLong() -> IntValue(value.toInt())
|
||||
KotlinBuiltIns.isShort(notNullExpected) && value == value.toShort().toLong() -> ShortValue(value.toShort())
|
||||
KotlinBuiltIns.isByte(notNullExpected) && value == value.toByte().toLong() -> ByteValue(value.toByte())
|
||||
KotlinBuiltIns.isChar(notNullExpected) -> IntValue(value.toInt())
|
||||
else -> null
|
||||
return if (isUnsigned) {
|
||||
when {
|
||||
KotlinBuiltIns.isUByte(notNullExpected) && value == value.toByte().toLong() -> UByteValue(value.toByte())
|
||||
KotlinBuiltIns.isUShort(notNullExpected) && value == value.toShort().toLong() -> UShortValue(value.toShort())
|
||||
KotlinBuiltIns.isUInt(notNullExpected) && value == value.toInt().toLong() -> UIntValue(value.toInt())
|
||||
KotlinBuiltIns.isULong(notNullExpected) -> ULongValue(value)
|
||||
else -> null
|
||||
}
|
||||
} else {
|
||||
when {
|
||||
KotlinBuiltIns.isLong(notNullExpected) -> LongValue(value)
|
||||
KotlinBuiltIns.isInt(notNullExpected) && value == value.toInt().toLong() -> IntValue(value.toInt())
|
||||
KotlinBuiltIns.isShort(notNullExpected) && value == value.toShort().toLong() -> ShortValue(value.toShort())
|
||||
KotlinBuiltIns.isByte(notNullExpected) && value == value.toByte().toLong() -> ByteValue(value.toByte())
|
||||
KotlinBuiltIns.isChar(notNullExpected) -> IntValue(value.toInt())
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+34
-7
@@ -17,14 +17,20 @@
|
||||
package org.jetbrains.kotlin.resolve.constants
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import java.util.*
|
||||
|
||||
class IntegerValueTypeConstructor(
|
||||
private val value: Long,
|
||||
private val builtIns: KotlinBuiltIns
|
||||
private val value: Long,
|
||||
private val module: ModuleDescriptor,
|
||||
parameters: CompileTimeConstant.Parameters
|
||||
) : TypeConstructor {
|
||||
private val supertypes = ArrayList<KotlinType>(4)
|
||||
|
||||
@@ -32,10 +38,28 @@ class IntegerValueTypeConstructor(
|
||||
// order of types matters
|
||||
// 'getPrimitiveNumberType' returns first of supertypes that is a subtype of expected type
|
||||
// for expected type 'Any' result type 'Int' should be returned
|
||||
checkBoundsAndAddSuperType(value, Integer.MIN_VALUE.toLong(), Integer.MAX_VALUE.toLong(), builtIns.intType)
|
||||
checkBoundsAndAddSuperType(value, java.lang.Byte.MIN_VALUE.toLong(), java.lang.Byte.MAX_VALUE.toLong(), builtIns.byteType)
|
||||
checkBoundsAndAddSuperType(value, java.lang.Short.MIN_VALUE.toLong(), java.lang.Short.MAX_VALUE.toLong(), builtIns.shortType)
|
||||
supertypes.add(builtIns.longType)
|
||||
val isUnsigned = parameters.isUnsigned
|
||||
|
||||
// TODO: fix value ranges for unsigned types
|
||||
checkBoundsAndAddSuperType(
|
||||
value,
|
||||
Integer.MIN_VALUE.toLong(),
|
||||
Integer.MAX_VALUE.toLong(),
|
||||
if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uInt) else builtIns.intType
|
||||
)
|
||||
checkBoundsAndAddSuperType(
|
||||
value,
|
||||
java.lang.Byte.MIN_VALUE.toLong(),
|
||||
java.lang.Byte.MAX_VALUE.toLong(),
|
||||
if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uByte) else builtIns.byteType
|
||||
)
|
||||
checkBoundsAndAddSuperType(
|
||||
value,
|
||||
java.lang.Short.MIN_VALUE.toLong(),
|
||||
java.lang.Short.MAX_VALUE.toLong(),
|
||||
if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uShort) else builtIns.shortType
|
||||
)
|
||||
supertypes.add(if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uLong) else builtIns.longType)
|
||||
}
|
||||
|
||||
private fun checkBoundsAndAddSuperType(value: Long, minValue: Long, maxValue: Long, kotlinType: KotlinType) {
|
||||
@@ -44,6 +68,9 @@ class IntegerValueTypeConstructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun unsignedType(classId: ClassId): SimpleType =
|
||||
module.findClassAcrossModuleDependencies(classId)?.defaultType ?: ErrorUtils.createErrorType("Error type for $classId")
|
||||
|
||||
override fun getSupertypes(): Collection<KotlinType> = supertypes
|
||||
|
||||
override fun getParameters(): List<TypeParameterDescriptor> = emptyList()
|
||||
@@ -57,7 +84,7 @@ class IntegerValueTypeConstructor(
|
||||
fun getValue(): Long = value
|
||||
|
||||
override fun getBuiltIns(): KotlinBuiltIns {
|
||||
return builtIns
|
||||
return module.builtIns
|
||||
}
|
||||
|
||||
override fun toString() = "IntegerValueType($value)"
|
||||
|
||||
@@ -40,9 +40,7 @@ abstract class ConstantValue<out T>(open val value: T) {
|
||||
}
|
||||
|
||||
abstract class IntegerValueConstant<out T> protected constructor(value: T) : ConstantValue<T>(value)
|
||||
abstract class UnsignedValueConstant<out T> protected constructor(value: T, private val kotlinType: KotlinType) : ConstantValue<T>(value) {
|
||||
override fun getType(module: ModuleDescriptor): KotlinType = kotlinType
|
||||
}
|
||||
abstract class UnsignedValueConstant<out T> protected constructor(value: T) : ConstantValue<T>(value)
|
||||
|
||||
class AnnotationValue(value: AnnotationDescriptor) : ConstantValue<AnnotationDescriptor>(value) {
|
||||
override fun getType(module: ModuleDescriptor): KotlinType = value.type
|
||||
@@ -193,25 +191,45 @@ class StringValue(value: String) : ConstantValue<String>(value) {
|
||||
override fun toString() = "\"$value\""
|
||||
}
|
||||
|
||||
class UByteValue(byteValue: ByteValue, kotlinType: KotlinType) : UnsignedValueConstant<Byte>(byteValue.value, kotlinType) {
|
||||
class UByteValue(byteValue: Byte) : UnsignedValueConstant<Byte>(byteValue) {
|
||||
override fun getType(module: ModuleDescriptor): KotlinType {
|
||||
return module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uByte)?.defaultType
|
||||
?: ErrorUtils.createErrorType("Unsigned type UByte not found")
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUByteValue(this, data)
|
||||
|
||||
override fun toString() = "$value.toUByte()"
|
||||
}
|
||||
|
||||
class UShortValue(shortValue: ShortValue, kotlinType: KotlinType) : UnsignedValueConstant<Short>(shortValue.value, kotlinType) {
|
||||
class UShortValue(shortValue: Short) : UnsignedValueConstant<Short>(shortValue) {
|
||||
override fun getType(module: ModuleDescriptor): KotlinType {
|
||||
return module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uShort)?.defaultType
|
||||
?: ErrorUtils.createErrorType("Unsigned type UByte not found")
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUShortValue(this, data)
|
||||
|
||||
override fun toString() = "$value.toUShort()"
|
||||
}
|
||||
|
||||
class UIntValue(intValue: IntValue, kotlinType: KotlinType) : UnsignedValueConstant<Int>(intValue.value, kotlinType) {
|
||||
class UIntValue(intValue: Int) : UnsignedValueConstant<Int>(intValue) {
|
||||
override fun getType(module: ModuleDescriptor): KotlinType {
|
||||
return module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uInt)?.defaultType
|
||||
?: ErrorUtils.createErrorType("Unsigned type UByte not found")
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitUIntValue(this, data)
|
||||
|
||||
override fun toString() = "$value.toUInt()"
|
||||
}
|
||||
|
||||
class ULongValue(longValue: LongValue, kotlinType: KotlinType) : UnsignedValueConstant<Long>(longValue.value, kotlinType) {
|
||||
class ULongValue(longValue: Long) : UnsignedValueConstant<Long>(longValue) {
|
||||
override fun getType(module: ModuleDescriptor): KotlinType {
|
||||
return module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uLong)?.defaultType
|
||||
?: ErrorUtils.createErrorType("Unsigned type UByte not found")
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitULongValue(this, data)
|
||||
|
||||
override fun toString() = "$value.toULong()"
|
||||
|
||||
@@ -15,6 +15,9 @@ import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor;
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
@@ -445,6 +448,27 @@ public class TypeUtils {
|
||||
if (supertypes.contains(longType)) {
|
||||
return longType;
|
||||
}
|
||||
|
||||
KotlinType uIntType = findByFqName(supertypes, KotlinBuiltIns.FQ_NAMES.uIntFqName);
|
||||
if (uIntType != null) return uIntType;
|
||||
|
||||
KotlinType uLongType = findByFqName(supertypes, KotlinBuiltIns.FQ_NAMES.uLongFqName);
|
||||
if (uLongType != null) return uLongType;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static KotlinType findByFqName(@NotNull Collection<KotlinType> supertypes, FqName fqName) {
|
||||
for (KotlinType supertype : supertypes) {
|
||||
ClassifierDescriptor descriptor = supertype.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor == null) continue;
|
||||
|
||||
FqNameUnsafe descriptorFqName = DescriptorUtils.getFqName(descriptor);
|
||||
if (descriptorFqName.equals(fqName.toUnsafe())) {
|
||||
return supertype;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user