Analysis API: fix invalid constant value kind for unsigned numbers
This commit is contained in:
+23
-8
@@ -34,14 +34,26 @@ internal object FirCompileTimeConstantEvaluator {
|
|||||||
// TODO: Handle boolean operators, const property loading, class reference, array, annotation values, etc.
|
// TODO: Handle boolean operators, const property loading, class reference, array, annotation values, etc.
|
||||||
fun evaluate(expression: FirExpression): FirConstExpression<*>? =
|
fun evaluate(expression: FirExpression): FirConstExpression<*>? =
|
||||||
when (expression) {
|
when (expression) {
|
||||||
is FirConstExpression<*> -> expression
|
is FirConstExpression<*> -> expression.adaptToConstKind()
|
||||||
is FirFunctionCall -> evaluate(expression)
|
is FirFunctionCall -> evaluate(expression)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun evaluateAsKtConstantExpression(expression: FirExpression): KtConstantValue? {
|
fun evaluateAsKtConstantExpression(expression: FirExpression): KtConstantValue? {
|
||||||
val evaluated = evaluate(expression) ?: return null
|
val evaluated = evaluate(expression) ?: return null
|
||||||
return KtConstantValueFactory.createConstantValue(evaluated.value, evaluated.psi as? KtElement)
|
|
||||||
|
val ktConstantValue = KtConstantValueFactory.createConstantValue(evaluated.value, evaluated.psi as? KtElement) ?: return null
|
||||||
|
check(ktConstantValue.constantValueKind == evaluated.kind) {
|
||||||
|
"Expected ${evaluated.kind} for created KtConstantValue but ${ktConstantValue.constantValueKind} found"
|
||||||
|
}
|
||||||
|
return ktConstantValue
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirConstExpression<*>.adaptToConstKind(): FirConstExpression<*> {
|
||||||
|
return kind.toConstExpression(
|
||||||
|
source,
|
||||||
|
kind.convertToNumber(value as? Number) ?: value
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Rework to handle nested expressions
|
// TODO: Rework to handle nested expressions
|
||||||
@@ -81,7 +93,7 @@ internal object FirCompileTimeConstantEvaluator {
|
|||||||
// Lastly, we should preserve the resolved type of the original function call.
|
// Lastly, we should preserve the resolved type of the original function call.
|
||||||
return expression.apply {
|
return expression.apply {
|
||||||
replaceTypeRef(expectedType)
|
replaceTypeRef(expectedType)
|
||||||
} ?: this
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> ConstantValueKind<T>.toCompileTimeType(): CompileTimeType {
|
private fun <T> ConstantValueKind<T>.toCompileTimeType(): CompileTimeType {
|
||||||
@@ -195,7 +207,7 @@ internal object FirCompileTimeConstantEvaluator {
|
|||||||
else -> error("Unknown constant value")
|
else -> error("Unknown constant value")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ConstantValueKind<*>.convertToNumber(value: Number?): Number? {
|
private fun ConstantValueKind<*>.convertToNumber(value: Number?): Any? {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -206,14 +218,17 @@ internal object FirCompileTimeConstantEvaluator {
|
|||||||
this == ConstantValueKind.Int -> value.toInt()
|
this == ConstantValueKind.Int -> value.toInt()
|
||||||
this == ConstantValueKind.Long -> value.toLong()
|
this == ConstantValueKind.Long -> value.toLong()
|
||||||
this == ConstantValueKind.Short -> value.toShort()
|
this == ConstantValueKind.Short -> value.toShort()
|
||||||
|
this == ConstantValueKind.UnsignedByte -> value.toLong().toUByte()
|
||||||
|
this == ConstantValueKind.UnsignedShort -> value.toLong().toUShort()
|
||||||
|
this == ConstantValueKind.UnsignedInt -> value.toLong().toUInt()
|
||||||
|
this == ConstantValueKind.UnsignedLong -> value.toLong().toULong()
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> ConstantValueKind<T>?.toConstExpression(source: KtSourceElement?, value: Any): FirConstExpression<T>? =
|
private fun <T> ConstantValueKind<T>.toConstExpression(source: KtSourceElement?, value: Any?): FirConstExpression<T> =
|
||||||
if (this == null) null else
|
@Suppress("UNCHECKED_CAST")
|
||||||
@Suppress("UNCHECKED_CAST")
|
buildConstExpression(source, this, value as T)
|
||||||
buildConstExpression(source, this, value as T)
|
|
||||||
|
|
||||||
private fun FirFunctionCall.getOriginalFunction(): FirCallableDeclaration? {
|
private fun FirFunctionCall.getOriginalFunction(): FirCallableDeclaration? {
|
||||||
val symbol: FirBasedSymbol<*>? = when (val reference = calleeReference) {
|
val symbol: FirBasedSymbol<*>? = when (val reference = calleeReference) {
|
||||||
|
|||||||
Reference in New Issue
Block a user