AA: special handling for converted constants

This commit is contained in:
Jinseong Jeon
2022-04-20 23:53:04 -07:00
committed by Ilya Kirillov
parent faf6939515
commit 61cca31b6b
11 changed files with 114 additions and 16 deletions
@@ -64,6 +64,18 @@ public class Fe10IdeNormalAnalysisSourceModuleCompileTimeConstantEvaluatorTestGe
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_minusOne_justOne.kt");
}
@Test
@TestMetadata("integerLiteral_plusOne_entire.kt")
public void testIntegerLiteral_plusOne_entire() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_plusOne_entire.kt");
}
@Test
@TestMetadata("integerLiteral_plusOne_justOne.kt")
public void testIntegerLiteral_plusOne_justOne() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_plusOne_justOne.kt");
}
@Test
@TestMetadata("namedReference_const.kt")
public void testNamedReference_const() throws Exception {
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.api.fir.components
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValueFactory
import org.jetbrains.kotlin.analysis.api.components.KtCompileTimeConstantProvider
import org.jetbrains.kotlin.analysis.api.components.KtConstantEvaluationMode
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
@@ -15,11 +16,16 @@ import org.jetbrains.kotlin.analysis.api.withValidityAssertion
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPrefixExpression
import org.jetbrains.kotlin.types.ConstantValueKind
internal class KtFirCompileTimeConstantProvider(
override val analysisSession: KtFirAnalysisSession,
@@ -35,17 +41,24 @@ internal class KtFirCompileTimeConstantProvider(
private fun evaluateFir(
fir: FirElement?,
context: KtExpression,
sourcePsi: KtExpression,
mode: KtConstantEvaluationMode,
): KtConstantValue? = withValidityAssertion {
when (fir) {
is FirConstExpression<*> -> {
val v = FirCompileTimeConstantEvaluator.evaluateAsKtConstantValue(fir, mode)
if (v != null && fir.isConverted(sourcePsi)) {
val value = fir.kind.unaryMinus(v.value as? Number) ?: return null
KtConstantValueFactory.createConstantValue(value, v.sourcePsi)
} else v
}
is FirPropertyAccessExpression,
is FirExpression,
is FirNamedReference -> {
try {
FirCompileTimeConstantEvaluator.evaluateAsKtConstantValue(fir, mode)
} catch (e: ArithmeticException) {
KtConstantValue.KtErrorConstantValue(e.localizedMessage, context)
KtConstantValue.KtErrorConstantValue(e.localizedMessage, sourcePsi)
}
}
// For invalid code like the following,
@@ -57,7 +70,27 @@ internal class KtFirCompileTimeConstantProvider(
// `false` does not have a corresponding elements on the FIR side and hence the containing `FirWhenBranch` is returned. In this
// case, we simply report null since FIR does not know about it.
is FirWhenBranch -> null
else -> throwUnexpectedFirElementError(fir, context)
else -> throwUnexpectedFirElementError(fir, sourcePsi)
}
}
private fun FirConstExpression<*>.isConverted(sourcePsi: KtExpression): Boolean {
val firSourcePsi = this.source?.psi ?: return false
return firSourcePsi is KtPrefixExpression && firSourcePsi.operationToken == KtTokens.MINUS && firSourcePsi != sourcePsi
}
private fun ConstantValueKind<*>.unaryMinus(value: Number?): Any? {
if (value == null) {
return null
}
return when (this) {
ConstantValueKind.Byte -> value.toByte().unaryMinus()
ConstantValueKind.Double -> value.toDouble().unaryMinus()
ConstantValueKind.Float -> value.toFloat().unaryMinus()
ConstantValueKind.Int -> value.toInt().unaryMinus()
ConstantValueKind.Long -> value.toLong().unaryMinus()
ConstantValueKind.Short -> value.toShort().unaryMinus()
else -> null
}
}
}
@@ -258,17 +258,17 @@ internal object FirCompileTimeConstantEvaluator {
if (value == null) {
return null
}
return when {
this == ConstantValueKind.Byte -> value.toByte()
this == ConstantValueKind.Double -> value.toDouble()
this == ConstantValueKind.Float -> value.toFloat()
this == ConstantValueKind.Int -> value.toInt()
this == ConstantValueKind.Long -> value.toLong()
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()
return when (this) {
ConstantValueKind.Byte -> value.toByte()
ConstantValueKind.Double -> value.toDouble()
ConstantValueKind.Float -> value.toFloat()
ConstantValueKind.Int -> value.toInt()
ConstantValueKind.Long -> value.toLong()
ConstantValueKind.Short -> value.toShort()
ConstantValueKind.UnsignedByte -> value.toLong().toUByte()
ConstantValueKind.UnsignedShort -> value.toLong().toUShort()
ConstantValueKind.UnsignedInt -> value.toLong().toUInt()
ConstantValueKind.UnsignedLong -> value.toLong().toULong()
else -> null
}
}
@@ -64,6 +64,18 @@ public class FirIdeDependentAnalysisSourceModuleCompileTimeConstantEvaluatorTest
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_minusOne_justOne.kt");
}
@Test
@TestMetadata("integerLiteral_plusOne_entire.kt")
public void testIntegerLiteral_plusOne_entire() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_plusOne_entire.kt");
}
@Test
@TestMetadata("integerLiteral_plusOne_justOne.kt")
public void testIntegerLiteral_plusOne_justOne() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_plusOne_justOne.kt");
}
@Test
@TestMetadata("namedReference_const.kt")
public void testNamedReference_const() throws Exception {
@@ -64,6 +64,18 @@ public class FirIdeNormalAnalysisSourceModuleCompileTimeConstantEvaluatorTestGen
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_minusOne_justOne.kt");
}
@Test
@TestMetadata("integerLiteral_plusOne_entire.kt")
public void testIntegerLiteral_plusOne_entire() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_plusOne_entire.kt");
}
@Test
@TestMetadata("integerLiteral_plusOne_justOne.kt")
public void testIntegerLiteral_plusOne_justOne() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_plusOne_justOne.kt");
}
@Test
@TestMetadata("namedReference_const.kt")
public void testNamedReference_const() throws Exception {
@@ -64,6 +64,18 @@ public class FirStandaloneNormalAnalysisSourceModuleCompileTimeConstantEvaluator
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_minusOne_justOne.kt");
}
@Test
@TestMetadata("integerLiteral_plusOne_entire.kt")
public void testIntegerLiteral_plusOne_entire() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_plusOne_entire.kt");
}
@Test
@TestMetadata("integerLiteral_plusOne_justOne.kt")
public void testIntegerLiteral_plusOne_justOne() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/integerLiteral_plusOne_justOne.kt");
}
@Test
@TestMetadata("namedReference_const.kt")
public void testNamedReference_const() throws Exception {
@@ -1,9 +1,9 @@
expression: 1
CONSTANT_EXPRESSION_EVALUATION
constant: -1
constant: 1
constantValueKind: Int
CONSTANT_LIKE_EXPRESSION_EVALUATION
constantLike: -1
constantLike: 1
constantLikeValueKind: Int
@@ -0,0 +1,4 @@
annotation class Annotation(vararg val values: Int)
@Annotation(<expr>+1</expr>)
class C
@@ -0,0 +1,9 @@
expression: +1
CONSTANT_EXPRESSION_EVALUATION
constant: 1
constantValueKind: Int
CONSTANT_LIKE_EXPRESSION_EVALUATION
constantLike: 1
constantLikeValueKind: Int
@@ -0,0 +1,4 @@
annotation class Annotation(vararg val values: Int)
@Annotation(+<expr>1</expr>)
class C