Analysis API: separate constant values from annotation values

This commit is contained in:
Ilya Kirillov
2021-11-23 20:44:39 +01:00
parent 47c1da2845
commit f722a54c78
53 changed files with 302 additions and 415 deletions
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.Fe10KtAnalysisSessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtConstantValue
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
@@ -21,7 +22,7 @@ internal class KtFe10CompileTimeConstantProvider(
override val token: ValidityToken
get() = analysisSession.token
override fun evaluate(expression: KtExpression): KtAnnotationValue? {
override fun evaluate(expression: KtExpression): KtConstantValue? {
val bindingContext = analysisContext.analyze(expression)
val constant = ConstantExpressionEvaluator.getPossiblyErrorConstant(expression, bindingContext)
return constant?.toConstantValue(TypeUtils.NO_EXPECTED_TYPE)?.toKtConstantValue()
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.ba
import org.jetbrains.kotlin.analysis.api.*
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValueFactory
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.*
@@ -266,37 +268,34 @@ internal val MemberDescriptor.ktModality: Modality
return this.modality
}
internal fun ConstantValue<*>.toKtConstantValue(): KtAnnotationValue {
internal fun ConstantValue<*>.toKtConstantValue(): KtConstantValue {
return when (this) {
is BooleanValue -> KtLiteralAnnotationValue(ConstantValueKind.Boolean, value, null)
is CharValue -> KtLiteralAnnotationValue(ConstantValueKind.Char, value, null)
is ByteValue -> KtLiteralAnnotationValue(ConstantValueKind.Byte, value, null)
is UByteValue -> KtLiteralAnnotationValue(ConstantValueKind.UnsignedByte, value, null)
is ShortValue -> KtLiteralAnnotationValue(ConstantValueKind.Short, value, null)
is UShortValue -> KtLiteralAnnotationValue(ConstantValueKind.UnsignedShort, value, null)
is IntValue -> KtLiteralAnnotationValue(ConstantValueKind.Int, value, null)
is UIntValue -> KtLiteralAnnotationValue(ConstantValueKind.UnsignedInt, value, null)
is LongValue -> KtLiteralAnnotationValue(ConstantValueKind.Long, value, null)
is ULongValue -> KtLiteralAnnotationValue(ConstantValueKind.UnsignedLong, value, null)
is FloatValue -> KtLiteralAnnotationValue(ConstantValueKind.Float, value, null)
is DoubleValue -> KtLiteralAnnotationValue(ConstantValueKind.Double, value, null)
is NullValue -> KtLiteralAnnotationValue(ConstantValueKind.Null, null, null)
is StringValue -> KtLiteralAnnotationValue(ConstantValueKind.String, value, null)
is ArrayValue -> KtArrayAnnotationValue(value.map { it.toKtConstantValue() }, null)
is ErrorValue.ErrorValueWithMessage -> KtConstantValue.KtErrorConstantValue(message, sourcePsi = null)
else -> {
KtConstantValueFactory.createConstantValue(value)
?: error("Unexpected constant value $value")
}
}
}
internal fun ConstantValue<*>.toKtAnnotationValue(): KtAnnotationValue {
return when (this) {
is ArrayValue -> KtArrayAnnotationValue(value.map { it.toKtAnnotationValue() }, null)
is EnumValue -> KtEnumEntryAnnotationValue(CallableId(enumClassId, enumEntryName), null)
is AnnotationValue -> {
val arguments = value.allValueArguments.map { (name, v) -> KtNamedAnnotationValue(name.asString(), v.toKtConstantValue()) }
KtAnnotationApplicationValue(
KtAnnotationApplication(
value.annotationClass?.classId,
psi = null,
useSiteTarget = null,
arguments = arguments
arguments = arguments,
)
)
}
is ErrorValue -> KtErrorValue(this.toString())
else -> KtUnsupportedAnnotationValue
is KClassValue -> KtKClassValue(cl)
else -> {
KtConstantAnnotationValue(toKtConstantValue())
}
}
}
@@ -436,6 +435,11 @@ internal fun AnnotationDescriptor.toKtAnnotationApplication(): KtAnnotationAppli
annotationClass?.maybeLocalClassId,
(source as? PsiSourceElement)?.psi as? KtAnnotationEntry,
(this as? LazyAnnotationDescriptor)?.annotationEntry?.useSiteTarget?.getAnnotationUseSiteTarget(),
allValueArguments.map { (name, value) -> KtNamedAnnotationValue(name.asString(), value.toKtConstantValue()) }
getKtNamedAnnotationArguments(),
)
}
}
internal fun AnnotationDescriptor.getKtNamedAnnotationArguments() =
allValueArguments.map { (name, value) ->
KtNamedAnnotationValue(name.asString(), value.toKtAnnotationValue())
}
@@ -8,14 +8,11 @@ package org.jetbrains.kotlin.analysis.api.descriptors.utils
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
import org.jetbrains.kotlin.analysis.api.components.RendererModifier
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.*
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.classId
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.isExplicitOverride
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.ktModality
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.ktVisibility
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtConstantValueRenderer
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.descriptors.*
@@ -31,9 +28,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
import org.jetbrains.kotlin.resolve.source.getPsi
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.api.descriptors.utils
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.classId
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getKtNamedAnnotationArguments
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.maybeLocalClassId
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtConstantValue
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
@@ -88,7 +89,7 @@ internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, pr
}
private fun KtFe10RendererConsumer.renderTypeAnnotationDebug(annotation: AnnotationDescriptor) {
val namedValues = annotation.allValueArguments.map { KtNamedAnnotationValue(it.key.asString(), it.value.toKtConstantValue()) }
val namedValues = annotation.getKtNamedAnnotationArguments()
renderAnnotationDebug(annotation.annotationClass?.classId, namedValues)
}
@@ -115,9 +116,8 @@ internal class KtFe10TypeRenderer(private val options: KtTypeRendererOptions, pr
is KtArrayAnnotationValue ->
renderList(value.values, separator = ", ", prefix = "[", postfix = "]") { renderConstantValueDebug(it) }
is KtEnumEntryAnnotationValue -> append(value.callableId)
is KtLiteralAnnotationValue<*> -> append(value.constantValueKind.asString).append("(").append(value.value).append(")")
is KtConstantAnnotationValue -> append(value.constantValue.constantValueKind.asString).append("(").append(value.constantValue.value).append(")")
KtUnsupportedAnnotationValue -> append(KtUnsupportedAnnotationValue::class.java.simpleName)
is KtErrorValue -> append("<ERROR>")
}
}
@@ -7,7 +7,8 @@ package org.jetbrains.kotlin.analysis.api.descriptors.utils
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.classId
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtConstantValue
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtConstantValueRenderer
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationValueRenderer
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtAnnotationValue
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.ClassId
@@ -31,7 +32,7 @@ internal fun KtFe10RendererConsumer.renderFe10Annotations(annotations: Annotatio
renderList(valueArguments, separator = ", ", prefix = "(", postfix = ")", renderWhenEmpty = false) { (name, value) ->
append(name.render())
append(" = ")
append(KtConstantValueRenderer.render(value.toKtConstantValue()))
append(KtAnnotationValueRenderer.render(value.toKtAnnotationValue()))
}
append(' ')
@@ -24,54 +24,6 @@ public class KtFe10CompileTimeConstantEvaluatorTestGenerated extends AbstractKtF
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("annotationInAnnotation_arrayOf.kt")
public void testAnnotationInAnnotation_arrayOf() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_arrayOf.kt");
}
@Test
@TestMetadata("annotationInAnnotation_collectionLiteral.kt")
public void testAnnotationInAnnotation_collectionLiteral() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_collectionLiteral.kt");
}
@Test
@TestMetadata("annotationInAnnotation_collectionLiteral_spread.kt")
public void testAnnotationInAnnotation_collectionLiteral_spread() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_collectionLiteral_spread.kt");
}
@Test
@TestMetadata("annotationInAnnotation_multipleAnnotations_arrayOf.kt")
public void testAnnotationInAnnotation_multipleAnnotations_arrayOf() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_multipleAnnotations_arrayOf.kt");
}
@Test
@TestMetadata("annotationInAnnotation_multipleAnnotations_collectionLiteral.kt")
public void testAnnotationInAnnotation_multipleAnnotations_collectionLiteral() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_multipleAnnotations_collectionLiteral.kt");
}
@Test
@TestMetadata("annotationInAnnotation_single.kt")
public void testAnnotationInAnnotation_single() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_single.kt");
}
@Test
@TestMetadata("annotationInAnnotation_vararg.kt")
public void testAnnotationInAnnotation_vararg() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_vararg.kt");
}
@Test
@TestMetadata("enumAsAnnotationValue.kt")
public void testEnumAsAnnotationValue() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/enumAsAnnotationValue.kt");
}
@Test
@TestMetadata("propertyInit_Byte.kt")
public void testPropertyInit_Byte() throws Exception {
@@ -8,8 +8,7 @@ package org.jetbrains.kotlin.analysis.api.fir
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication
import org.jetbrains.kotlin.analysis.api.fir.annotations.fullyExpandedClassId
import org.jetbrains.kotlin.analysis.api.fir.annotations.mapAnnotationParameters
import org.jetbrains.kotlin.analysis.api.fir.evaluate.KtFirConstantValueConverter
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
@@ -26,7 +25,6 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirImplicitInvokeCall
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtCallElement
import org.jetbrains.kotlin.util.OperatorNameConventions
/**
@@ -80,7 +78,7 @@ internal fun FirAnnotation.toKtAnnotationApplication(useSiteSession: FirSession)
fullyExpandedClassId(useSiteSession),
psi as? KtAnnotationEntry,
useSiteTarget,
KtFirConstantValueConverter.toNamedConstantValue(
FirAnnotationValueConverter.toNamedConstantValue(
mapAnnotationParameters(this, useSiteSession),
useSiteSession,
)
@@ -5,18 +5,18 @@
package org.jetbrains.kotlin.analysis.api.fir.components
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationValue
import org.jetbrains.kotlin.analysis.api.annotations.KtErrorValue
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirCompileTimeConstantEvaluator
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.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.KtFirConstantValueConverter
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirCompileTimeConstantEvaluator
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.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenBranch
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
internal class KtFirCompileTimeConstantProvider(
@@ -24,14 +24,13 @@ internal class KtFirCompileTimeConstantProvider(
override val token: ValidityToken,
) : KtCompileTimeConstantProvider(), KtFirAnalysisSessionComponent {
override fun evaluate(expression: KtExpression): KtAnnotationValue? = withValidityAssertion {
override fun evaluate(expression: KtExpression): KtConstantValue? = withValidityAssertion {
when (val fir = expression.getOrBuildFir(firResolveState)) {
is FirExpression -> {
try {
FirCompileTimeConstantEvaluator.evaluate(fir)?.let { KtFirConstantValueConverter.toConstantValue(it) }
?: KtFirConstantValueConverter.toConstantValue(fir, firResolveState.rootModuleSession)
FirCompileTimeConstantEvaluator.evaluateAsKtConstantExpression(fir)
} catch (e: ArithmeticException) {
KtErrorValue(e.localizedMessage)
KtConstantValue.KtErrorConstantValue(e.localizedMessage, fir.psi as? KtElement)
}
}
// For invalid code like the following,
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.api.fir.evaluate
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.base.KtConstantValueFactory
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
@@ -20,8 +21,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.resolve.ArrayFqNames
internal object KtFirConstantValueConverter {
internal object FirAnnotationValueConverter {
fun toNamedConstantValue(
argumentMapping: Map<String, FirExpression>,
session: FirSession,
@@ -33,13 +33,10 @@ internal object KtFirConstantValueConverter {
)
}
fun <T> toConstantValue(
firConstExpression: FirConstExpression<T>,
): KtLiteralAnnotationValue<T> =
firConstExpression.convertConstantExpression()
private fun <T> FirConstExpression<T>.convertConstantExpression(): KtLiteralAnnotationValue<T> =
KtLiteralAnnotationValue(kind, value, psi as? KtElement)
private fun <T> FirConstExpression<T>.convertConstantExpression(): KtConstantAnnotationValue? {
val constantValue = KtConstantValueFactory.createConstantValue(value, psi as? KtElement) ?: return null
return KtConstantAnnotationValue(constantValue)
}
private fun Collection<FirExpression>.convertConstantExpression(
session: FirSession,
@@ -6,7 +6,8 @@
package org.jetbrains.kotlin.analysis.api.fir.evaluate
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValueFactory
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
@@ -14,10 +15,12 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.argument
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.constants.evaluate.CompileTimeType
import org.jetbrains.kotlin.resolve.constants.evaluate.evalBinaryOp
import org.jetbrains.kotlin.resolve.constants.evaluate.evalUnaryOp
@@ -28,7 +31,6 @@ import org.jetbrains.kotlin.types.ConstantValueKind
* and the argument, are compile-time constant as well.
*/
internal object FirCompileTimeConstantEvaluator {
// TODO: Handle boolean operators, const property loading, class reference, array, annotation values, etc.
fun evaluate(expression: FirExpression): FirConstExpression<*>? =
when (expression) {
@@ -37,9 +39,9 @@ internal object FirCompileTimeConstantEvaluator {
else -> null
}
fun evaluateAsKtConstantExpression(expression: FirExpression): KtAnnotationValue? {
fun evaluateAsKtConstantExpression(expression: FirExpression): KtConstantValue? {
val evaluated = evaluate(expression) ?: return null
return KtFirConstantValueConverter.toConstantValue(evaluated)
return KtConstantValueFactory.createConstantValue(evaluated.value, evaluated.psi as? KtElement)
}
// TODO: Rework to handle nested expressions
@@ -106,7 +108,7 @@ internal object FirCompileTimeConstantEvaluator {
kind.toCompileTimeType(),
kind.convertToNumber(value as? Number)!!
)?.let {
it.toConstantValueKind()?.toConstExpression(source, it)
it.toConstantValueKind().toConstExpression(source, it)
}
}
@@ -123,7 +125,7 @@ internal object FirCompileTimeConstantEvaluator {
other.kind.toCompileTimeType(),
other.kind.convertToNumber(other.value as? Number)!!
)?.let {
it.toConstantValueKind()?.toConstExpression(source, it)
it.toConstantValueKind().toConstExpression(source, it)
}
}
@@ -176,7 +178,7 @@ internal object FirCompileTimeConstantEvaluator {
else -> null
}
private fun <T : Any> T.toConstantValueKind(): ConstantValueKind<*>? =
private fun <T> T.toConstantValueKind(): ConstantValueKind<*> =
when (this) {
is Byte -> ConstantValueKind.Byte
is Double -> ConstantValueKind.Double
@@ -189,7 +191,8 @@ internal object FirCompileTimeConstantEvaluator {
is String -> ConstantValueKind.String
is Boolean -> ConstantValueKind.Boolean
else -> null
null -> ConstantValueKind.Null
else -> error("Unknown constant value")
}
private fun ConstantValueKind<*>.convertToNumber(value: Number?): Number? {
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.analysis.api.fir.renderer
import org.jetbrains.kotlin.analysis.api.fir.annotations.mapAnnotationParameters
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirCompileTimeConstantEvaluator
import org.jetbrains.kotlin.analysis.api.fir.evaluate.KtFirConstantValueConverter
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtConstantValueRenderer
import org.jetbrains.kotlin.analysis.api.fir.evaluate.FirAnnotationValueConverter
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationValueRenderer
import org.jetbrains.kotlin.analysis.api.annotations.KtUnsupportedAnnotationValue
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.fir.FirSession
@@ -57,8 +57,8 @@ private fun renderAndSortAnnotationArguments(descriptor: FirAnnotation, session:
private fun renderConstant(value: FirExpression, useSiteSession: FirSession): String {
val evaluated = FirCompileTimeConstantEvaluator.evaluate(value)
val constantValue = KtFirConstantValueConverter.toConstantValue(evaluated ?: value, useSiteSession)
val constantValue = FirAnnotationValueConverter.toConstantValue(evaluated ?: value, useSiteSession)
?: KtUnsupportedAnnotationValue
return KtConstantValueRenderer.render(constantValue)
return KtAnnotationValueRenderer.render(constantValue)
}
@@ -24,54 +24,6 @@ public class FirCompileTimeConstantEvaluatorTestGenerated extends AbstractFirCom
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("annotationInAnnotation_arrayOf.kt")
public void testAnnotationInAnnotation_arrayOf() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_arrayOf.kt");
}
@Test
@TestMetadata("annotationInAnnotation_collectionLiteral.kt")
public void testAnnotationInAnnotation_collectionLiteral() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_collectionLiteral.kt");
}
@Test
@TestMetadata("annotationInAnnotation_collectionLiteral_spread.kt")
public void testAnnotationInAnnotation_collectionLiteral_spread() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_collectionLiteral_spread.kt");
}
@Test
@TestMetadata("annotationInAnnotation_multipleAnnotations_arrayOf.kt")
public void testAnnotationInAnnotation_multipleAnnotations_arrayOf() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_multipleAnnotations_arrayOf.kt");
}
@Test
@TestMetadata("annotationInAnnotation_multipleAnnotations_collectionLiteral.kt")
public void testAnnotationInAnnotation_multipleAnnotations_collectionLiteral() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_multipleAnnotations_collectionLiteral.kt");
}
@Test
@TestMetadata("annotationInAnnotation_single.kt")
public void testAnnotationInAnnotation_single() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_single.kt");
}
@Test
@TestMetadata("annotationInAnnotation_vararg.kt")
public void testAnnotationInAnnotation_vararg() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/annotationInAnnotation_vararg.kt");
}
@Test
@TestMetadata("enumAsAnnotationValue.kt")
public void testEnumAsAnnotationValue() throws Exception {
runTest("analysis/analysis-api/testData/components/compileTimeConstantProvider/evaluate/enumAsAnnotationValue.kt");
}
@Test
@TestMetadata("propertyInit_Byte.kt")
public void testPropertyInit_Byte() throws Exception {
@@ -5,7 +5,8 @@
package org.jetbrains.kotlin.analysis.api.impl.base.test.components.compileTimeConstantProvider
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.annotations.render
import org.jetbrains.kotlin.analysis.api.base.render
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.expressionMarkerProvider
import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleFileTest
@@ -31,47 +32,10 @@ abstract class AbstractCompileTimeConstantEvaluatorTest(
}
val actual = buildString {
appendLine("expression: ${expression.text}")
appendLine("constant_value: ${analyseForTest(expression) { constantValue?.stringRepresentation() }}")
appendLine("constant: ${(constantValue as? KtLiteralAnnotationValue<*>)?.toConst()}")
appendLine("constant: ${constantValue?.render()}")
appendLine("constantValueKind: ${constantValue?.constantValueKind}")
}
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
}
private fun KtAnnotationValue.stringRepresentation(): String {
return when (this) {
is KtArrayAnnotationValue -> buildString {
appendLine("KtArrayConstantValue [")
appendLine(INDENT, values.joinToString(separator = "\n") { it.stringRepresentation() })
append("]")
}
is KtAnnotationApplicationValue -> buildString {
append("KtAnnotationConstantValue(")
append(annotationValue.classId?.relativeClassName)
append(", ")
annotationValue.arguments.joinTo(this, separator = ", ", prefix = "(", postfix = ")") {
"${it.name} = ${it.expression.stringRepresentation()}"
}
append(")")
}
is KtEnumEntryAnnotationValue -> buildString {
append("KtEnumEntryConstantValue(")
append("$callableId")
append(")")
}
is KtLiteralAnnotationValue<*> -> buildString {
append("KtLiteralConstantValue(")
append("constantValueKind=${constantValueKind}")
append(", ")
append("value=${value})")
}
is KtErrorValue -> "KtErrorValue($message)"
is KtUnsupportedAnnotationValue -> "KtUnsupportedConstantValue"
}
}
private fun StringBuilder.appendLine(indent: Int, value: String) {
appendLine(value.prependIndent(" ".repeat(indent)))
}
}
private const val INDENT = 2
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.api
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.psi.KtExpression
public sealed class KtInitializerValue {
@@ -13,7 +14,7 @@ public sealed class KtInitializerValue {
}
public class KtConstantInitializerValue(
public val constant: KtAnnotationValue,
public val constant: KtConstantValue,
override val initializerPsi: KtExpression?
) : KtInitializerValue()
@@ -5,9 +5,10 @@
package org.jetbrains.kotlin.analysis.api.annotations
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.types.ConstantValueKind
/**
* Annotation values are expected to be compile-time constants. According to the
@@ -19,7 +20,7 @@ import org.jetbrains.kotlin.types.ConstantValueKind
* * other annotation types, and
* * array of aforementioned types
*
* [KtLiteralAnnotationValue] covers first two kinds;
* [KtConstantAnnotationValue] covers first two kinds;
* [KtEnumEntryAnnotationValue] corresponds to enum types;
* [KtAnnotationApplicationValue] represents annotation types (with annotation fq name and arguments); and
* [KtArrayAnnotationValue] abstracts an array of [KtAnnotationValue]s.
@@ -28,12 +29,6 @@ public sealed class KtAnnotationValue(
public open val sourcePsi: KtElement? = null
)
/**
* This represents an error during expression evaluation or constant conversion.
*/
public class KtErrorValue(
public val message: String
) : KtAnnotationValue()
/**
* This represents an unsupported expression used as an annotation value.
@@ -47,33 +42,19 @@ public class KtArrayAnnotationValue(
public class KtAnnotationApplicationValue(
public val annotationValue: KtAnnotationApplication,
) : KtAnnotationValue()
) : KtAnnotationValue() {
override val sourcePsi: KtElement? get() = annotationValue.psi
}
public class KtEnumEntryAnnotationValue(
public val callableId: CallableId?,
override val sourcePsi: KtElement?,
) : KtAnnotationValue()
public class KtLiteralAnnotationValue<T>(
public val constantValueKind: ConstantValueKind<T>,
public val value: T,
override val sourcePsi: KtElement?,
) : KtAnnotationValue() {
public fun toConst(): Any? {
return (value as? Long)?.let {
when (constantValueKind) {
ConstantValueKind.Byte -> it.toByte()
ConstantValueKind.Short -> it.toShort()
ConstantValueKind.Int -> it.toInt()
ConstantValueKind.Float -> it.toFloat()
ConstantValueKind.Double -> it.toDouble()
public class KtConstantAnnotationValue(
public val constantValue: KtConstantValue,
) : KtAnnotationValue()
ConstantValueKind.UnsignedByte -> it.toUByte()
ConstantValueKind.UnsignedShort -> it.toUShort()
ConstantValueKind.UnsignedInt -> it.toUInt()
ConstantValueKind.UnsignedLong -> it.toULong()
else -> it
}
} ?: value
}
}
public fun KtAnnotationValue.render(): String =
KtAnnotationValueRenderer.render(this)
@@ -3,12 +3,9 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.symbols.markers
package org.jetbrains.kotlin.analysis.api.annotations
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.types.ConstantValueKind
public object KtConstantValueRenderer {
public object KtAnnotationValueRenderer {
public fun render(value: KtAnnotationValue): String = buildString {
renderConstantValue(value)
}
@@ -24,11 +21,8 @@ public object KtConstantValueRenderer {
is KtEnumEntryAnnotationValue -> {
renderEnumEntryConstantValue(value)
}
is KtErrorValue -> {
append("ERROR")
}
is KtLiteralAnnotationValue<*> -> {
renderLiteralConstantValue(value)
is KtConstantAnnotationValue -> {
renderConstantAnnotationValue(value)
}
KtUnsupportedAnnotationValue -> {
append("KtUnsupportedConstantValue")
@@ -36,22 +30,8 @@ public object KtConstantValueRenderer {
}
}
private fun StringBuilder.renderLiteralConstantValue(value: KtLiteralAnnotationValue<*>) {
when (value.constantValueKind) {
ConstantValueKind.String -> {
append('"')
append(value.value)
append('"')
}
ConstantValueKind.Char -> {
append("'")
append(value.value)
append("'")
}
else -> {
append(value.value)
}
}
private fun StringBuilder.renderConstantAnnotationValue(value: KtConstantAnnotationValue) {
append(KtConstantValueRenderer.render(value.constantValue))
}
private fun StringBuilder.renderEnumEntryConstantValue(value: KtEnumEntryAnnotationValue) {
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.annotations
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.types.ConstantValueKind
public object KtConstantValueRenderer {
public fun render(value: KtConstantValue): String = buildString {
when (value) {
is KtConstantValue.KtStringConstantValue -> {
append('"')
append(value.value)
append('"')
}
is KtConstantValue.KtCharConstantValue -> {
append("'")
append(value.value)
append("'")
}
is KtConstantValue.KtErrorConstantValue -> {
append("error(\"${value.errorMessage}\")")
}
else -> {
append(value.value)
}
}
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.base
import org.jetbrains.kotlin.analysis.api.annotations.KtConstantValueRenderer
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.types.ConstantValueKind
public sealed class KtConstantValue(public val constantValueKind: ConstantValueKind<*>) {
public abstract val value: Any?
public abstract val sourcePsi: KtElement?
public class KtNullConstantValue(override val sourcePsi: KtElement?) : KtConstantValue(ConstantValueKind.Null) {
override val value: Nothing? get() = null
}
public class KtBooleanConstantValue(
override val value: Boolean,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.Boolean)
public class KtCharConstantValue(
override val value: Char,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.Char)
public class KtByteConstantValue(
override val value: Byte,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.Byte)
public class KtUnsignedByteConstantValue(
override val value: UByte,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.UnsignedByte)
public class KtShortConstantValue(
override val value: Short,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.Short)
public class KtUnsignedShortConstantValue(
override val value: UShort,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.UnsignedShort)
public class KtIntConstantValue(
override val value: Int,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.Int)
public class KtUnsignedIntConstantValue(
override val value: UInt,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.UnsignedInt)
public class KtLongConstantValue(
override val value: Long,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.Long)
public class KtUnsignedLongConstantValue(
override val value: ULong,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.UnsignedLong)
public class KtStringConstantValue(
override val value: String,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.String)
public class KtFloatConstantValue(
override val value: Float,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.Float)
public class KtDoubleConstantValue(
override val value: Double,
override val sourcePsi: KtElement?
) : KtConstantValue(ConstantValueKind.Double)
public class KtErrorConstantValue(
public val errorMessage: String,
override val sourcePsi: KtElement?,
) : KtConstantValue(ConstantValueKind.Error) {
override val value: ERROR_VALUE get() = ERROR_VALUE
public object ERROR_VALUE
}
}
public fun KtConstantValue.render(): String =
KtConstantValueRenderer.render(this)
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.base
import org.jetbrains.kotlin.psi.KtElement
public object KtConstantValueFactory {
public fun createConstantValue(value: Any?, expression: KtElement? = null): KtConstantValue? = when (value) {
null -> KtConstantValue.KtNullConstantValue(expression)
is Boolean -> KtConstantValue.KtBooleanConstantValue(value, expression)
is Char -> KtConstantValue.KtCharConstantValue(value, expression)
is Byte -> KtConstantValue.KtByteConstantValue(value, expression)
is UByte -> KtConstantValue.KtUnsignedByteConstantValue(value, expression)
is Short -> KtConstantValue.KtShortConstantValue(value, expression)
is UShort -> KtConstantValue.KtUnsignedShortConstantValue(value, expression)
is Int -> KtConstantValue.KtIntConstantValue(value, expression)
is UInt -> KtConstantValue.KtUnsignedIntConstantValue(value, expression)
is Long -> KtConstantValue.KtLongConstantValue(value, expression)
is ULong -> KtConstantValue.KtUnsignedLongConstantValue(value, expression)
is String -> KtConstantValue.KtStringConstantValue(value, expression)
is Float -> KtConstantValue.KtFloatConstantValue(value, expression)
is Double -> KtConstantValue.KtDoubleConstantValue(value, expression)
else -> null
}
}
@@ -5,14 +5,14 @@
package org.jetbrains.kotlin.analysis.api.components
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.psi.KtExpression
public abstract class KtCompileTimeConstantProvider : KtAnalysisSessionComponent() {
public abstract fun evaluate(expression: KtExpression): KtAnnotationValue?
public abstract fun evaluate(expression: KtExpression): KtConstantValue?
}
public interface KtCompileTimeConstantProviderMixIn : KtAnalysisSessionMixIn {
public fun KtExpression.evaluate(): KtAnnotationValue? =
public fun KtExpression.evaluate(): KtConstantValue? =
analysisSession.compileTimeConstantProvider.evaluate(this)
}
@@ -12,6 +12,7 @@ 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.annotations.*
import org.jetbrains.kotlin.analysis.api.base.render
import org.jetbrains.kotlin.analysis.api.components.KtSymbolInfoProviderMixIn
import org.jetbrains.kotlin.analysis.api.symbols.markers.*
import org.jetbrains.kotlin.analysis.api.types.KtClassErrorType
@@ -138,8 +139,8 @@ public object DebugSymbolRenderer {
append(")")
}
private fun Block.renderConstantValue(value: KtAnnotationValue) {
append(KtConstantValueRenderer.render(value))
private fun Block.renderAnnotationValue(value: KtAnnotationValue) {
append(KtAnnotationValueRenderer.render(value))
}
private fun Block.renderNamedConstantValue(value: KtNamedAnnotationValue) {
@@ -188,7 +189,7 @@ public object DebugSymbolRenderer {
// Symbol-related values
is KtSymbol -> renderSymbolTag(value)
is KtType -> renderType(value)
is KtAnnotationValue -> renderConstantValue(value)
is KtAnnotationValue -> renderAnnotationValue(value)
is KtNamedAnnotationValue -> renderNamedConstantValue(value)
is KtInitializerValue -> renderKtInitializerValue(value)
is KtAnnotationApplication -> renderAnnotationApplication(value)
@@ -215,7 +216,7 @@ public object DebugSymbolRenderer {
when (value) {
is KtConstantInitializerValue -> {
append("KtConstantInitializerValue(")
renderConstantValue(value.constant)
append(value.constant.render())
append(")")
}
is KtNonConstantInitializerValue -> {
@@ -1,6 +0,0 @@
annotation class Annotation(vararg val strings: String)
annotation class AnnotationInner(val value: Annotation)
@AnnotationInner(<expr>Annotation(strings = arrayOf("v1", "v2"))</expr>)
class C
@@ -1,6 +0,0 @@
expression: Annotation(strings = arrayOf("v1", "v2"))
constant_value: KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [
KtLiteralConstantValue(constantValueKind=String, value=v1)
KtLiteralConstantValue(constantValueKind=String, value=v2)
]))
constant: null
@@ -1,6 +0,0 @@
annotation class Annotation(vararg val strings: String)
annotation class AnnotationInner(val value: Annotation)
@AnnotationInner(<expr>Annotation(strings = ["v1", "v2"])</expr>)
class C
@@ -1,6 +0,0 @@
expression: Annotation(strings = ["v1", "v2"])
constant_value: KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [
KtLiteralConstantValue(constantValueKind=String, value=v1)
KtLiteralConstantValue(constantValueKind=String, value=v2)
]))
constant: null
@@ -1,6 +0,0 @@
annotation class Annotation(vararg val strings: String)
annotation class AnnotationInner(val value: Annotation)
@AnnotationInner(<expr>Annotation(*["v1", "v2"])</expr>)
class C
@@ -1,6 +0,0 @@
expression: Annotation(*["v1", "v2"])
constant_value: KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [
KtLiteralConstantValue(constantValueKind=String, value=v1)
KtLiteralConstantValue(constantValueKind=String, value=v2)
]))
constant: null
@@ -1,6 +0,0 @@
annotation class Annotation(vararg val strings: String)
annotation class AnnotationArray(vararg val annos: Annotation)
@AnnotationArray(annos = <expr>arrayOf(Annotation("v1", "v2"), Annotation(strings = arrayOf("v3", "v4")))</expr>)
class C
@@ -1,12 +0,0 @@
expression: arrayOf(Annotation("v1", "v2"), Annotation(strings = arrayOf("v3", "v4")))
constant_value: KtArrayConstantValue [
KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [
KtLiteralConstantValue(constantValueKind=String, value=v1)
KtLiteralConstantValue(constantValueKind=String, value=v2)
]))
KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [
KtLiteralConstantValue(constantValueKind=String, value=v3)
KtLiteralConstantValue(constantValueKind=String, value=v4)
]))
]
constant: null
@@ -1,6 +0,0 @@
annotation class Annotation(vararg val strings: String)
annotation class AnnotationArray(vararg val annos: Annotation)
@AnnotationArray(annos = <expr>[Annotation("v1", "v2"), Annotation(strings = ["v3", "v4"])]</expr>)
class C
@@ -1,12 +0,0 @@
expression: [Annotation("v1", "v2"), Annotation(strings = ["v3", "v4"])]
constant_value: KtArrayConstantValue [
KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [
KtLiteralConstantValue(constantValueKind=String, value=v1)
KtLiteralConstantValue(constantValueKind=String, value=v2)
]))
KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [
KtLiteralConstantValue(constantValueKind=String, value=v3)
KtLiteralConstantValue(constantValueKind=String, value=v4)
]))
]
constant: null
@@ -1,6 +0,0 @@
annotation class Annotation(vararg val strings: String)
annotation class AnnotationInner(val value: Annotation)
@AnnotationInner(<expr>Annotation("v1")</expr>)
class C
@@ -1,5 +0,0 @@
expression: Annotation("v1")
constant_value: KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [
KtLiteralConstantValue(constantValueKind=String, value=v1)
]))
constant: null
@@ -1,6 +0,0 @@
annotation class Annotation(vararg val strings: String)
annotation class AnnotationInner(val value: Annotation)
@AnnotationInner(<expr>Annotation("v1", "v2")</expr>)
class C
@@ -1,6 +0,0 @@
expression: Annotation("v1", "v2")
constant_value: KtAnnotationConstantValue(Annotation, (strings = KtArrayConstantValue [
KtLiteralConstantValue(constantValueKind=String, value=v1)
KtLiteralConstantValue(constantValueKind=String, value=v2)
]))
constant: null
@@ -1,10 +0,0 @@
enum class Color {
R,
G,
B
}
annotation class Annotation(val color : Color)
@Annotation(<expr>Color.R</expr>)
class C
@@ -1,3 +0,0 @@
expression: Color.R
constant_value: KtEnumEntryConstantValue(/Color.R)
constant: null
@@ -1,3 +1,3 @@
expression: 42
constant_value: KtLiteralConstantValue(constantValueKind=Byte, value=42)
constant: 42
constantValueKind: Byte
@@ -1,3 +1,3 @@
expression: 42 / 0
constant_value: KtErrorValue(Division by zero)
constant: null
constant: error("Division by zero")
constantValueKind: Error
@@ -1,3 +1,3 @@
expression: 42 / 0
constant_value: KtErrorValue(/ by zero)
constant: null
constant: error("/ by zero")
constantValueKind: Error
@@ -1,3 +1,3 @@
expression: 3.14
constant_value: KtLiteralConstantValue(constantValueKind=Double, value=3.14)
constant: 3.14
constantValueKind: Double
@@ -1,3 +1,3 @@
expression: 3.14f
constant_value: KtLiteralConstantValue(constantValueKind=Float, value=3.14)
constant: 3.14
constantValueKind: Float
@@ -1,3 +1,3 @@
expression: 42
constant_value: KtLiteralConstantValue(constantValueKind=Int, value=42)
constant: 42
constantValueKind: Int
@@ -1,3 +1,3 @@
expression: 42
constant_value: KtLiteralConstantValue(constantValueKind=Long, value=42)
constant: 42
constantValueKind: Long
@@ -1,3 +1,3 @@
expression: 42u
constant_value: KtLiteralConstantValue(constantValueKind=UInt, value=42)
constant: 42
constantValueKind: Long
@@ -1,3 +1,3 @@
expression: "42"
constant_value: KtLiteralConstantValue(constantValueKind=String, value=42)
constant: 42
constant: "42"
constantValueKind: String
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.annotations.KtLiteralAnnotationValue
import org.jetbrains.kotlin.analysis.api.annotations.KtConstantAnnotationValue
internal fun KtAnnotatedSymbol.hasJvmSyntheticAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean =
hasAnnotation("kotlin/jvm/JvmSynthetic", annotationUseSiteTarget)
@@ -31,7 +31,7 @@ internal fun KtAnnotatedSymbol.getJvmNameFromAnnotation(annotationUseSiteTarget:
}
return annotation?.let {
(it.arguments.firstOrNull()?.expression as? KtLiteralAnnotationValue<*>)?.value as? String
(it.arguments.firstOrNull()?.expression as? KtConstantAnnotationValue)?.constantValue?.value as? String
}
}
@@ -13,7 +13,8 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.analysis.api.isValid
import org.jetbrains.kotlin.analysis.api.symbols.KtKotlinPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.analysis.api.annotations.KtLiteralAnnotationValue
import org.jetbrains.kotlin.analysis.api.annotations.KtConstantAnnotationValue
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
@@ -113,7 +114,7 @@ internal class FirLightFieldForPropertySymbol(
if (!propertySymbol.isConst) return@lazyPub null
if (!propertySymbol.isVal) return@lazyPub null
val constInitializer = propertySymbol.initializer as? KtConstantInitializerValue ?: return@lazyPub null
(constInitializer.constant as? KtLiteralAnnotationValue<*>)?.createPsiLiteral(this)
(constInitializer.constant as? KtConstantValue)?.createPsiLiteral(this)
}
override fun getInitializer(): PsiExpression? = _initializer
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
import org.jetbrains.kotlin.analysis.api.components.DefaultTypeClassIds
import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
@@ -184,36 +185,36 @@ internal fun KtAnnotationValue.toAnnotationMemberValue(parent: PsiElement): PsiA
annotationValue.arguments,
annotationValue.psi
)
else ->
createPsiLiteral(parent)?.let {
is KtConstantAnnotationValue -> {
this.constantValue.createPsiLiteral(parent)?.let {
when (it) {
is PsiLiteral -> FirPsiLiteral(sourcePsi, parent, it)
else -> FirPsiExpression(sourcePsi, parent, it)
}
}
}
is KtEnumEntryAnnotationValue -> {
val fqName = this.callableId?.asSingleFqName()?.asString() ?: return null
val psiExpression = PsiElementFactory.getInstance(parent.project).createExpressionFromText(fqName, parent)
FirPsiExpression(sourcePsi, parent, psiExpression)
}
KtUnsupportedAnnotationValue -> null
}
}
private fun KtAnnotationValue.asStringForPsiLiteral(): String? =
when (this) {
is KtEnumEntryAnnotationValue ->
"${callableId?.classId?.asSingleFqName()?.asString() ?: ""}.${callableId?.callableName}"
is KtLiteralAnnotationValue<*> -> {
when (val value = this.value) {
is String -> "\"${escapeString(value)}\""
is Long -> "${value}L"
is Float -> "${value}f"
else -> value?.toString() ?: "null"
}
}
else -> null
private fun KtConstantValue.asStringForPsiLiteral(): String =
when (val value = value) {
is String -> "\"${escapeString(value)}\""
is Long -> "${value}L"
is Float -> "${value}f"
else -> value?.toString() ?: "null"
}
internal fun KtAnnotationValue.createPsiLiteral(parent: PsiElement): PsiExpression? {
val asString = asStringForPsiLiteral() ?: return null
val instance = PsiElementFactory.getInstance(parent.project)
internal fun KtConstantValue.createPsiLiteral(parent: PsiElement): PsiExpression? {
val asString = asStringForPsiLiteral()
return try {
instance.createExpressionFromText(asString, parent)
PsiElementFactory.getInstance(parent.project).createExpressionFromText(asString, parent)
} catch (_: IncorrectOperationException) {
null
}
@@ -824,6 +824,9 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
+value.toString()
+">"
}
ConstantValueKind.Error -> {
+"ERROR_CONSTANT"
}
}
}
@@ -290,6 +290,7 @@ private fun ConstantValueKind<*>.toIrConstKind(): IrConstKind<*> = when (this) {
ConstantValueKind.Float -> IrConstKind.Float
ConstantValueKind.Double -> IrConstKind.Double
ConstantValueKind.IntegerLiteral, ConstantValueKind.UnsignedIntegerLiteral -> throw IllegalArgumentException()
ConstantValueKind.Error -> throw IllegalArgumentException()
}
@@ -128,5 +128,6 @@ fun ConstantValueKind<*>.expectedConeType(session: FirSession): ConeKotlinType {
ConstantValueKind.IntegerLiteral -> constructLiteralType(StandardClassIds.Int)
ConstantValueKind.UnsignedIntegerLiteral -> constructLiteralType(StandardClassIds.UInt)
ConstantValueKind.Error -> error("Unexpected error ConstantValueKind")
}
}
@@ -24,6 +24,8 @@ sealed class ConstantValueKind<T>(val asString: kotlin.String) {
object Float : ConstantValueKind<kotlin.Float>("Float")
object Double : ConstantValueKind<kotlin.Double>("Double")
object Error : ConstantValueKind<Nothing>("Error")
object IntegerLiteral : ConstantValueKind<kotlin.Long>("IntegerLiteral")
object UnsignedIntegerLiteral : ConstantValueKind<kotlin.Long>("UnsignedIntegerLiteral")