From 1f93630a9cb8a91912104614f5dd2600a0489b41 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Thu, 24 Feb 2022 15:55:52 -0800 Subject: [PATCH] AA: evaluate constant property initializers --- ...ileTimeConstantEvaluatorTestGenerated.java | 36 +++++++++++++++++-- .../KtFirCompileTimeConstantProvider.kt | 31 ++++++++++++++-- ...ileTimeConstantEvaluatorTestGenerated.java | 36 +++++++++++++++++-- .../evaluate/namedReference_const.kt | 8 +++++ .../evaluate/namedReference_const.txt | 3 ++ .../evaluate/namedReference_val.kt | 8 +++++ .../evaluate/namedReference_val.txt | 3 ++ ...amedReference.kt => namedReference_var.kt} | 0 ...edReference.txt => namedReference_var.txt} | 0 .../evaluate/propertyInCompanionObject.kt | 11 ++++++ .../evaluate/propertyInCompanionObject.txt | 3 ++ .../propertyInCompanionObject_indirect.kt | 12 +++++++ .../propertyInCompanionObject_indirect.txt | 3 ++ ...ropertyInCompanionObject_indirect_twice.kt | 13 +++++++ ...opertyInCompanionObject_indirect_twice.txt | 3 ++ 15 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_const.kt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_const.txt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_val.kt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_val.txt rename analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/{namedReference.kt => namedReference_var.kt} (100%) rename analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/{namedReference.txt => namedReference_var.txt} (100%) create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject.kt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject.txt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect.kt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect.txt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect_twice.kt create mode 100644 analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect_twice.txt diff --git a/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/fe10/components/compileTimeConstantProvider/Fe10CompileTimeConstantEvaluatorTestGenerated.java b/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/fe10/components/compileTimeConstantProvider/Fe10CompileTimeConstantEvaluatorTestGenerated.java index 264961463b7..1543a5346bc 100644 --- a/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/fe10/components/compileTimeConstantProvider/Fe10CompileTimeConstantEvaluatorTestGenerated.java +++ b/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/fe10/components/compileTimeConstantProvider/Fe10CompileTimeConstantEvaluatorTestGenerated.java @@ -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 diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCompileTimeConstantProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCompileTimeConstantProvider.kt index fa6caf865a3..1e7c658a435 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCompileTimeConstantProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCompileTimeConstantProvider.kt @@ -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) } + } + } } diff --git a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/compileTimeConstantProvider/FirCompileTimeConstantEvaluatorTestGenerated.java b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/compileTimeConstantProvider/FirCompileTimeConstantEvaluatorTestGenerated.java index 4bd49cc4307..2cbc03528b1 100644 --- a/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/compileTimeConstantProvider/FirCompileTimeConstantEvaluatorTestGenerated.java +++ b/analysis/analysis-api-fir/tests/org/jetbrains/kotlin/analysis/api/fir/components/compileTimeConstantProvider/FirCompileTimeConstantEvaluatorTestGenerated.java @@ -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 diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_const.kt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_const.kt new file mode 100644 index 00000000000..fd1ee8e96db --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_const.kt @@ -0,0 +1,8 @@ +class Test { + const val bar : Int = 42 +} + +fun box() { + val t = Test() + t.bar +} diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_const.txt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_const.txt new file mode 100644 index 00000000000..9ff5cc75772 --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_const.txt @@ -0,0 +1,3 @@ +expression: bar +constant: 42 +constantValueKind: Int diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_val.kt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_val.kt new file mode 100644 index 00000000000..58ffcfe01e1 --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_val.kt @@ -0,0 +1,8 @@ +class Test { + val bar : Int = 42 +} + +fun box() { + val t = Test() + t.bar +} diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_val.txt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_val.txt new file mode 100644 index 00000000000..9ff5cc75772 --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_val.txt @@ -0,0 +1,3 @@ +expression: bar +constant: 42 +constantValueKind: Int diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference.kt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_var.kt similarity index 100% rename from analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference.kt rename to analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_var.kt diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference.txt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_var.txt similarity index 100% rename from analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference.txt rename to analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/namedReference_var.txt diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject.kt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject.kt new file mode 100644 index 00000000000..86ff6d158ae --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject.kt @@ -0,0 +1,11 @@ +package prop.`in`.`companion` + +class Test { + fun test() { + val x = someField + } + companion object { + // effectively constant + val someField = "something" + } +} diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject.txt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject.txt new file mode 100644 index 00000000000..a082d0ce5af --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject.txt @@ -0,0 +1,3 @@ +expression: someField +constant: "something" +constantValueKind: String diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect.kt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect.kt new file mode 100644 index 00000000000..dba0e6a3d90 --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect.kt @@ -0,0 +1,12 @@ +package prop.`in`.`companion`.indirect + +class Test { + fun test() { + val x = indirectPointer + } + companion object { + // effectively constant + val someField = "something" + val indirectPointer = someField + } +} diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect.txt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect.txt new file mode 100644 index 00000000000..82c273b3976 --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect.txt @@ -0,0 +1,3 @@ +expression: indirectPointer +constant: "something" +constantValueKind: String diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect_twice.kt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect_twice.kt new file mode 100644 index 00000000000..d5ea18b3ab2 --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect_twice.kt @@ -0,0 +1,13 @@ +package prop.`in`.`companion`.indirect.twice + +class Test { + fun test() { + val x = oneMore + } + companion object { + // effectively constant + val someField = "something" + val indirectPointer = someField + val oneMore = indirectPointer + } +} diff --git a/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect_twice.txt b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect_twice.txt new file mode 100644 index 00000000000..c493fcb415b --- /dev/null +++ b/analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/propertyInCompanionObject_indirect_twice.txt @@ -0,0 +1,3 @@ +expression: oneMore +constant: "something" +constantValueKind: String