AA: evaluate constant property initializers

This commit is contained in:
Jinseong Jeon
2022-02-24 15:55:52 -08:00
committed by Ilya Kirillov
parent 7ec7cc47a9
commit 1f93630a9c
15 changed files with 162 additions and 8 deletions
@@ -41,9 +41,39 @@ public class Fe10CompileTimeConstantEvaluatorTestGenerated extends AbstractCompi
}
@Test
@TestMetadata("namedReference.kt")
public void testNamedReference() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference.kt");
@TestMetadata("namedReference_const.kt")
public void testNamedReference_const() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_const.kt");
}
@Test
@TestMetadata("namedReference_val.kt")
public void testNamedReference_val() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_val.kt");
}
@Test
@TestMetadata("namedReference_var.kt")
public void testNamedReference_var() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_var.kt");
}
@Test
@TestMetadata("propertyInCompanionObject.kt")
public void testPropertyInCompanionObject() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject.kt");
}
@Test
@TestMetadata("propertyInCompanionObject_indirect.kt")
public void testPropertyInCompanionObject_indirect() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect.kt");
}
@Test
@TestMetadata("propertyInCompanionObject_indirect_twice.kt")
public void testPropertyInCompanionObject_indirect_twice() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect_twice.kt");
}
@Test
@@ -5,18 +5,26 @@
package org.jetbrains.kotlin.analysis.api.fir.components
import org.jetbrains.kotlin.analysis.api.KtConstantInitializerValue
import org.jetbrains.kotlin.analysis.api.KtInitializerValue
import org.jetbrains.kotlin.analysis.api.KtNonConstantInitializerValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.analysis.api.components.KtCompileTimeConstantProvider
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirCompileTimeConstantEvaluator
import org.jetbrains.kotlin.analysis.api.fir.symbols.getKtConstantInitializer
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
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.declarations.utils.referredPropertySymbol
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.psi
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.resolvedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
@@ -27,6 +35,9 @@ internal class KtFirCompileTimeConstantProvider(
override fun evaluate(expression: KtExpression): KtConstantValue? = withValidityAssertion {
when (val fir = expression.getOrBuildFir(firResolveState)) {
is FirPropertyAccessExpression -> {
fir.referredPropertySymbol?.toKtConstantValue()
}
is FirExpression -> {
try {
FirCompileTimeConstantEvaluator.evaluateAsKtConstantExpression(fir)
@@ -35,8 +46,10 @@ internal class KtFirCompileTimeConstantProvider(
}
}
is FirNamedReference -> {
// TODO: but... if it refers to a property with a constant initializer, we can retrieve that technically?
null
when (val resolvedSymbol = fir.resolvedSymbol) {
is FirPropertySymbol -> resolvedSymbol.toKtConstantValue()
else -> null
}
}
// For invalid code like the following,
// ```
@@ -50,4 +63,18 @@ internal class KtFirCompileTimeConstantProvider(
else -> throwUnexpectedFirElementError(fir, expression)
}
}
private fun FirPropertySymbol.toKtConstantValue(): KtConstantValue? = withValidityAssertion {
if (isVal) {
getKtConstantInitializer()?.toKtConstantValue()
} else null
}
private fun KtInitializerValue?.toKtConstantValue(): KtConstantValue? = withValidityAssertion {
when (this) {
null -> null
is KtConstantInitializerValue -> constant
is KtNonConstantInitializerValue -> initializerPsi?.let { evaluate(it) }
}
}
}
@@ -41,9 +41,39 @@ public class FirCompileTimeConstantEvaluatorTestGenerated extends AbstractCompil
}
@Test
@TestMetadata("namedReference.kt")
public void testNamedReference() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference.kt");
@TestMetadata("namedReference_const.kt")
public void testNamedReference_const() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_const.kt");
}
@Test
@TestMetadata("namedReference_val.kt")
public void testNamedReference_val() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_val.kt");
}
@Test
@TestMetadata("namedReference_var.kt")
public void testNamedReference_var() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_var.kt");
}
@Test
@TestMetadata("propertyInCompanionObject.kt")
public void testPropertyInCompanionObject() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject.kt");
}
@Test
@TestMetadata("propertyInCompanionObject_indirect.kt")
public void testPropertyInCompanionObject_indirect() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect.kt");
}
@Test
@TestMetadata("propertyInCompanionObject_indirect_twice.kt")
public void testPropertyInCompanionObject_indirect_twice() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect_twice.kt");
}
@Test
@@ -0,0 +1,8 @@
class Test {
const val bar : Int = 42
}
fun box() {
val t = Test()
t.<expr>bar</expr>
}
@@ -0,0 +1,3 @@
expression: bar
constant: 42
constantValueKind: Int
@@ -0,0 +1,8 @@
class Test {
val bar : Int = 42
}
fun box() {
val t = Test()
t.<expr>bar</expr>
}
@@ -0,0 +1,3 @@
expression: bar
constant: 42
constantValueKind: Int
@@ -0,0 +1,11 @@
package prop.`in`.`companion`
class Test {
fun test() {
val x = <expr>someField</expr>
}
companion object {
// effectively constant
val someField = "something"
}
}
@@ -0,0 +1,3 @@
expression: someField
constant: "something"
constantValueKind: String
@@ -0,0 +1,12 @@
package prop.`in`.`companion`.indirect
class Test {
fun test() {
val x = <expr>indirectPointer</expr>
}
companion object {
// effectively constant
val someField = "something"
val indirectPointer = someField
}
}
@@ -0,0 +1,3 @@
expression: indirectPointer
constant: "something"
constantValueKind: String
@@ -0,0 +1,13 @@
package prop.`in`.`companion`.indirect.twice
class Test {
fun test() {
val x = <expr>oneMore</expr>
}
companion object {
// effectively constant
val someField = "something"
val indirectPointer = someField
val oneMore = indirectPointer
}
}
@@ -0,0 +1,3 @@
expression: oneMore
constant: "something"
constantValueKind: String