[AA-FIR] Add support for constant evaluation of string templates.

Support FirStringConcatenationCall in FirCompileTimeConstantEvaluator.
This allows string templates ("foo${bar}") to be evaluated as constants,
assuming the interpolated expressions are themselves constant.

In addition, fixes some handling bugs with KtConstantEvaluationMode,
where some expressions that are not valid in a `const val` declaration
were being supported for `CONSTANT_EXPRESSION_EVALUATION`, including
non-static final Java fields in FIR, and composite expressions of
non-const properties in FE1.0.
This commit is contained in:
Justin Paupore
2023-02-13 20:16:15 -08:00
committed by Ilya Kirillov
parent 0193c83b05
commit fa517180b7
12 changed files with 100 additions and 23 deletions
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.utils.isConst
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
import org.jetbrains.kotlin.fir.psi
@@ -66,6 +67,9 @@ internal object FirCompileTimeConstantEvaluator {
is FirFunctionCall -> {
evaluateFunctionCall(fir, mode)
}
is FirStringConcatenationCall -> {
evaluateStringConcatenationCall(fir, mode)
}
is FirNamedReference -> {
fir.toResolvedPropertySymbol()?.toConstExpression(mode)
}
@@ -93,7 +97,7 @@ internal object FirCompileTimeConstantEvaluator {
mode: KtConstantEvaluationMode,
): FirConstExpression<*>? {
return when {
mode == KtConstantEvaluationMode.CONSTANT_EXPRESSION_EVALUATION && !isFinal -> null
mode == KtConstantEvaluationMode.CONSTANT_EXPRESSION_EVALUATION && !(isStatic && isFinal) -> null
isVal && hasInitializer -> {
evaluate(fir.initializer, mode)
}
@@ -152,6 +156,20 @@ internal object FirCompileTimeConstantEvaluator {
)
}
private fun evaluateStringConcatenationCall(
stringConcatenationCall: FirStringConcatenationCall,
mode: KtConstantEvaluationMode,
): FirConstExpression<String>? {
val concatenated = buildString {
for (arg in stringConcatenationCall.arguments) {
val evaluated = evaluate(arg, mode) ?: return null
append(evaluated.value.toString())
}
}
return ConstantValueKind.String.toConstExpression(stringConcatenationCall.source, concatenated)
}
private fun evaluateFunctionCall(
functionCall: FirFunctionCall,
mode: KtConstantEvaluationMode,
@@ -232,6 +232,18 @@ public class FirIdeDependentAnalysisSourceModuleCompileTimeConstantEvaluatorTest
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/string_plusTwice.kt");
}
@Test
@TestMetadata("string_templateConst.kt")
public void testString_templateConst() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/string_templateConst.kt");
}
@Test
@TestMetadata("string_templateNonConst.kt")
public void testString_templateNonConst() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/string_templateNonConst.kt");
}
@Test
@TestMetadata("string_toString.kt")
public void testString_toString() throws Exception {
@@ -232,6 +232,18 @@ public class FirIdeNormalAnalysisSourceModuleCompileTimeConstantEvaluatorTestGen
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/string_plusTwice.kt");
}
@Test
@TestMetadata("string_templateConst.kt")
public void testString_templateConst() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/string_templateConst.kt");
}
@Test
@TestMetadata("string_templateNonConst.kt")
public void testString_templateNonConst() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/string_templateNonConst.kt");
}
@Test
@TestMetadata("string_toString.kt")
public void testString_toString() throws Exception {