Introduce uL/UL suffix to represent numbers of unsigned long type

#KT-24663 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2018-06-26 15:38:24 +03:00
parent 7c44992016
commit a765ee41d7
16 changed files with 406 additions and 307 deletions
@@ -387,15 +387,19 @@ private class ConstantExpressionEvaluatorVisitor(
}
}
val isUnsigned = hasUnsignedSuffix(text)
val typedConstant = nodeElementType == KtNodeTypes.INTEGER_CONSTANT && (hasLongSuffix(text) || isUnsigned)
val isIntegerConstant = nodeElementType == KtNodeTypes.INTEGER_CONSTANT
val isUnsignedLong = isIntegerConstant && hasUnsignedLongSuffix(text)
val isUnsigned = isUnsignedLong || hasUnsignedSuffix(text)
val isTyped = isUnsigned || hasLongSuffix(text)
return createConstant(
result,
expectedType,
CompileTimeConstant.Parameters(
canBeUsedInAnnotation = true,
isPure = !typedConstant,
isPure = !isTyped,
isUnsignedNumberLiteral = isUnsigned,
isUnsignedLongNumberLiteral = isUnsignedLong,
usesVariableAsConstant = false,
usesNonConstValAsConstant = false
)
@@ -443,6 +447,7 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters(
isPure = false,
isUnsignedNumberLiteral = false,
isUnsignedLongNumberLiteral = false,
canBeUsedInAnnotation = canBeUsedInAnnotation,
usesVariableAsConstant = usesVariableAsConstant,
usesNonConstValAsConstant = usesNonConstantVariableAsConstant
@@ -506,6 +511,7 @@ private class ConstantExpressionEvaluatorVisitor(
canBeUsedInAnnotation = true,
isPure = false,
isUnsignedNumberLiteral = false,
isUnsignedLongNumberLiteral = false,
usesVariableAsConstant = leftConstant.usesVariableAsConstant || rightConstant.usesVariableAsConstant,
usesNonConstValAsConstant = leftConstant.usesNonConstValAsConstant || rightConstant.usesNonConstValAsConstant
)
@@ -553,7 +559,7 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters(
canBeUsedInAnnotation,
!isNumberConversionMethod && isArgumentPure,
false,
false, false,
usesVariableAsConstant, usesNonConstValAsConstant
)
)
@@ -586,7 +592,7 @@ private class ConstantExpressionEvaluatorVisitor(
val usesNonConstValAsConstant =
usesNonConstValAsConstant(argumentForReceiver.expression) || usesNonConstValAsConstant(argumentForParameter.expression)
val parameters = CompileTimeConstant.Parameters(
canBeUsedInAnnotation, areArgumentsPure, false, usesVariableAsConstant, usesNonConstValAsConstant
canBeUsedInAnnotation, areArgumentsPure, false, false, usesVariableAsConstant, usesNonConstValAsConstant
)
return when (resultingDescriptorName) {
OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression)?.wrap(parameters)
@@ -708,6 +714,7 @@ private class ConstantExpressionEvaluatorVisitor(
canBeUsedInAnnotation = isPropertyCompileTimeConstant(callableDescriptor),
isPure = false,
isUnsignedNumberLiteral = false,
isUnsignedLongNumberLiteral = false,
usesVariableAsConstant = true,
usesNonConstValAsConstant = !callableDescriptor.isConst
)
@@ -934,10 +941,16 @@ private class ConstantExpressionEvaluatorVisitor(
parameters: CompileTimeConstant.Parameters,
expectedType: KotlinType
): CompileTimeConstant<*>? {
if (parameters.isUnsignedLongNumberLiteral) {
return ULongValue(value).wrap(parameters)
}
if (TypeUtils.noExpectedType(expectedType) || expectedType.isError) {
return createIntegerValueTypeConstant(value, constantExpressionEvaluator.module, parameters)
}
val integerValue = ConstantValueFactory.createIntegerConstantValue(value, expectedType, parameters.isUnsignedNumberLiteral)
val integerValue = ConstantValueFactory.createIntegerConstantValue(
value, expectedType, parameters.isUnsignedNumberLiteral
)
if (integerValue != null) {
return integerValue.wrap(parameters)
}
@@ -962,14 +975,22 @@ private class ConstantExpressionEvaluatorVisitor(
canBeUsedInAnnotation: Boolean = this !is NullValue,
isPure: Boolean = false,
isUnsigned: Boolean = false,
isUnsignedLong: Boolean = false,
usesVariableAsConstant: Boolean = false,
usesNonConstValAsConstant: Boolean = false
): TypedCompileTimeConstant<T> =
wrap(CompileTimeConstant.Parameters(canBeUsedInAnnotation, isPure, isUnsigned, usesVariableAsConstant, usesNonConstValAsConstant))
wrap(
CompileTimeConstant.Parameters(
canBeUsedInAnnotation, isPure, isUnsigned, isUnsignedLong, usesVariableAsConstant, usesNonConstValAsConstant
)
)
}
private fun hasLongSuffix(text: String) = text.endsWith('l') || text.endsWith('L')
private fun hasUnsignedSuffix(text: String) = text.endsWith('u') || text.endsWith('U')
private fun hasUnsignedLongSuffix(text: String) =
text.endsWith("ul") || text.endsWith("uL") ||
text.endsWith("Ul") || text.endsWith("UL")
private fun parseNumericLiteral(text: String, type: IElementType): Any? {
val canonicalText = LiteralFormatUtil.removeUnderscores(text)
@@ -981,13 +1002,33 @@ private fun parseNumericLiteral(text: String, type: IElementType): Any? {
}
private fun parseLong(text: String): Long? {
return try {
val hasUnsignedSuffix = hasUnsignedSuffix(text)
val hasLongSuffix = hasLongSuffix(text)
val textWithoutSuffix = if (hasUnsignedSuffix || hasLongSuffix) text.substring(0, text.length - 1) else text
val (number, radix) = extractRadix(textWithoutSuffix)
fun String.removeSuffix(i: Int): String = this.substring(0, this.length - i)
if (hasUnsignedSuffix) {
return try {
val isUnsigned: Boolean
val numberWithoutSuffix: String
when {
hasUnsignedLongSuffix(text) -> {
isUnsigned = true
numberWithoutSuffix = text.removeSuffix(2)
}
hasUnsignedSuffix(text) -> {
isUnsigned = true
numberWithoutSuffix = text.removeSuffix(1)
}
hasLongSuffix(text) -> {
isUnsigned = false
numberWithoutSuffix = text.removeSuffix(1)
}
else -> {
isUnsigned = false
numberWithoutSuffix = text
}
}
val (number, radix) = extractRadix(numberWithoutSuffix)
if (isUnsigned) {
java.lang.Long.parseUnsignedLong(number, radix)
} else {
java.lang.Long.parseLong(number, radix)