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 {