[K2] Move ConstantValue from fir-serialization to compiler.common
This is needed to be able to save `ConstantValue` in map of evaluated constants.
This commit is contained in:
+4
-2
@@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.serialization
|
package org.jetbrains.kotlin.fir.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.constant.*
|
||||||
import org.jetbrains.kotlin.fir.serialization.constant.*
|
import org.jetbrains.kotlin.fir.serialization.constant.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.arrayElementType
|
import org.jetbrains.kotlin.fir.types.arrayElementType
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||||
@@ -13,7 +15,7 @@ import org.jetbrains.kotlin.metadata.deserialization.Flags
|
|||||||
internal object FirAnnotationArgumentVisitor : AnnotationArgumentVisitor<Unit, FirAnnotationArgumentVisitorData>() {
|
internal object FirAnnotationArgumentVisitor : AnnotationArgumentVisitor<Unit, FirAnnotationArgumentVisitorData>() {
|
||||||
override fun visitAnnotationValue(value: AnnotationValue, data: FirAnnotationArgumentVisitorData) {
|
override fun visitAnnotationValue(value: AnnotationValue, data: FirAnnotationArgumentVisitorData) {
|
||||||
data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.ANNOTATION
|
data.builder.type = ProtoBuf.Annotation.Argument.Value.Type.ANNOTATION
|
||||||
data.builder.annotation = data.serializer.serializeAnnotation(value.value)
|
data.builder.annotation = data.serializer.serializeAnnotation(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitArrayValue(value: ArrayValue, data: FirAnnotationArgumentVisitorData) {
|
override fun visitArrayValue(value: ArrayValue, data: FirAnnotationArgumentVisitorData) {
|
||||||
@@ -76,7 +78,7 @@ internal object FirAnnotationArgumentVisitor : AnnotationArgumentVisitor<Unit, F
|
|||||||
}
|
}
|
||||||
is KClassValue.Value.LocalClass -> {
|
is KClassValue.Value.LocalClass -> {
|
||||||
var arrayDimensions = 0
|
var arrayDimensions = 0
|
||||||
var type = classValue.type
|
var type = classValue.coneType<ConeKotlinType>()
|
||||||
while (true) {
|
while (true) {
|
||||||
type = type.arrayElementType() ?: break
|
type = type.arrayElementType() ?: break
|
||||||
arrayDimensions++
|
arrayDimensions++
|
||||||
|
|||||||
+35
-22
@@ -5,40 +5,53 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.serialization
|
package org.jetbrains.kotlin.fir.serialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.constant.AnnotationValue
|
||||||
|
import org.jetbrains.kotlin.constant.ConstantValue
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
|
||||||
import org.jetbrains.kotlin.fir.render
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.serialization.constant.ConstantValue
|
import org.jetbrains.kotlin.fir.serialization.constant.coneTypeSafe
|
||||||
import org.jetbrains.kotlin.fir.serialization.constant.toConstantValue
|
import org.jetbrains.kotlin.fir.serialization.constant.convertToConstantValues
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
|
||||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
class FirAnnotationSerializer(private val session: FirSession, internal val stringTable: FirElementAwareStringTable) {
|
class FirAnnotationSerializer(private val session: FirSession, internal val stringTable: FirElementAwareStringTable) {
|
||||||
fun serializeAnnotation(annotation: FirAnnotation): ProtoBuf.Annotation = ProtoBuf.Annotation.newBuilder().apply {
|
fun serializeAnnotation(annotation: FirAnnotation): ProtoBuf.Annotation {
|
||||||
val lookupTag = annotation.typeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag
|
return serializeAnnotation(
|
||||||
?: error { "Annotation without proper lookup tag: ${annotation.annotationTypeRef.coneType}" }
|
annotation.typeRef.coneTypeSafe<ConeClassLikeType>(),
|
||||||
|
annotation.argumentMapping.mapping.convertToConstantValues(session)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
id = lookupTag.toSymbol(session)?.let { stringTable.getFqNameIndex(it.fir) }
|
fun serializeAnnotation(annotation: AnnotationValue): ProtoBuf.Annotation {
|
||||||
?: stringTable.getQualifiedClassNameIndex(lookupTag.classId)
|
return serializeAnnotation(annotation.coneTypeSafe<ConeClassLikeType>(), annotation.value.argumentsMapping)
|
||||||
|
}
|
||||||
|
|
||||||
fun addArgument(argumentExpression: FirExpression, parameterName: Name) {
|
private fun serializeAnnotation(coneType: ConeClassLikeType?, argumentsMapping: Map<Name, ConstantValue<*>?>): ProtoBuf.Annotation {
|
||||||
val argument = ProtoBuf.Annotation.Argument.newBuilder()
|
return ProtoBuf.Annotation.newBuilder().apply {
|
||||||
argument.nameId = stringTable.getStringIndex(parameterName.asString())
|
val lookupTag = coneType?.lookupTag
|
||||||
val constantValue = argumentExpression.toConstantValue(session)
|
?: error { "Annotation without proper lookup tag: $coneType" }
|
||||||
?: error("Cannot convert expression ${argumentExpression.render()} to constant")
|
|
||||||
argument.setValue(valueProto(constantValue))
|
|
||||||
addArgument(argument)
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((name, argument) in annotation.argumentMapping.mapping) {
|
id = lookupTag.toSymbol(session)?.let { stringTable.getFqNameIndex(it.fir) }
|
||||||
addArgument(argument, name)
|
?: stringTable.getQualifiedClassNameIndex(lookupTag.classId)
|
||||||
}
|
|
||||||
}.build()
|
fun addArgument(argumentExpression: ConstantValue<*>?, parameterName: Name) {
|
||||||
|
if (argumentExpression == null) {
|
||||||
|
error("Cannot use null argument expression for parameter $parameterName")
|
||||||
|
}
|
||||||
|
val argument = ProtoBuf.Annotation.Argument.newBuilder()
|
||||||
|
argument.nameId = stringTable.getStringIndex(parameterName.asString())
|
||||||
|
argument.setValue(valueProto(argumentExpression))
|
||||||
|
addArgument(argument)
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((name, argument) in argumentsMapping) {
|
||||||
|
addArgument(argument, name)
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
|
||||||
internal fun valueProto(constant: ConstantValue<*>): ProtoBuf.Annotation.Argument.Value.Builder =
|
internal fun valueProto(constant: ConstantValue<*>): ProtoBuf.Annotation.Argument.Value.Builder =
|
||||||
ProtoBuf.Annotation.Argument.Value.newBuilder().apply {
|
ProtoBuf.Annotation.Argument.Value.newBuilder().apply {
|
||||||
|
|||||||
+3
-3
@@ -9,6 +9,9 @@ import org.jetbrains.kotlin.builtins.StandardNames
|
|||||||
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
|
import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.constant.EnumValue
|
||||||
|
import org.jetbrains.kotlin.constant.IntValue
|
||||||
|
import org.jetbrains.kotlin.constant.StringValue
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
@@ -29,9 +32,6 @@ import org.jetbrains.kotlin.fir.resolve.*
|
|||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
import org.jetbrains.kotlin.fir.scopes.*
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.serialization.constant.*
|
import org.jetbrains.kotlin.fir.serialization.constant.*
|
||||||
import org.jetbrains.kotlin.fir.serialization.constant.EnumValue
|
|
||||||
import org.jetbrains.kotlin.fir.serialization.constant.IntValue
|
|
||||||
import org.jetbrains.kotlin.fir.serialization.constant.StringValue
|
|
||||||
import org.jetbrains.kotlin.fir.serialization.constant.toConstantValue
|
import org.jetbrains.kotlin.fir.serialization.constant.toConstantValue
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||||
|
|||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.fir.serialization.constant
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.constant.AnnotationValue
|
||||||
|
import org.jetbrains.kotlin.constant.ConstantValue
|
||||||
|
import org.jetbrains.kotlin.constant.KClassValue
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
internal fun Map<Name, FirExpression>.convertToConstantValues(session: FirSession): Map<Name, ConstantValue<*>?> {
|
||||||
|
return this.map { (name, firExpression) ->
|
||||||
|
name to firExpression.toConstantValue(session)
|
||||||
|
}.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun LinkedHashMap<FirExpression, FirValueParameter>.convertToConstantValues(session: FirSession): Map<Name, ConstantValue<*>?> {
|
||||||
|
return this.map { (firExpression, firValueParameter) -> firValueParameter.name to firExpression }
|
||||||
|
.toMap().convertToConstantValues(session)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : ConeKotlinType> AnnotationValue.coneTypeSafe(): T? {
|
||||||
|
return this.value.type as? T
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : ConeKotlinType> KClassValue.Value.LocalClass.coneType(): T {
|
||||||
|
return this.type as T
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KClassValue.getArgumentType(session: FirSession): ConeKotlinType? {
|
||||||
|
when (val castedValue = value) {
|
||||||
|
is KClassValue.Value.LocalClass -> return castedValue.type as ConeKotlinType
|
||||||
|
is KClassValue.Value.NormalClass -> {
|
||||||
|
val (classId, arrayDimensions) = castedValue.value
|
||||||
|
val klass = session.symbolProvider.getClassLikeSymbolByClassId(classId)?.fir as? FirRegularClass ?: return null
|
||||||
|
var type: ConeClassLikeType = klass.defaultType().replaceArgumentsWithStarProjections()
|
||||||
|
repeat(arrayDimensions) {
|
||||||
|
type = type.createArrayType()
|
||||||
|
}
|
||||||
|
return type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun create(argumentType: ConeKotlinType): ConstantValue<*>? {
|
||||||
|
if (argumentType is ConeErrorType) return null
|
||||||
|
if (argumentType !is ConeClassLikeType) return null
|
||||||
|
var type = argumentType
|
||||||
|
var arrayDimensions = 0
|
||||||
|
while (true) {
|
||||||
|
if (type.isPrimitiveArray) break
|
||||||
|
type = type.arrayElementType() ?: break
|
||||||
|
arrayDimensions++
|
||||||
|
}
|
||||||
|
val classId = type.classId ?: return null
|
||||||
|
return KClassValue(classId, arrayDimensions)
|
||||||
|
}
|
||||||
+12
-25
@@ -5,25 +5,23 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.serialization.constant
|
package org.jetbrains.kotlin.fir.serialization.constant
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.constant.*
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
|
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isConst
|
import org.jetbrains.kotlin.fir.declarations.utils.isConst
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationArgumentMapping
|
import org.jetbrains.kotlin.fir.render
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall
|
|
||||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||||
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirArrayOfCallTransformer
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirArrayOfCallTransformer
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirArrayOfCallTransformer.Companion.isArrayOfCall
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirArrayOfCallTransformer.Companion.isArrayOfCall
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.types.classId
|
|
||||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
|
||||||
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
||||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||||
|
|
||||||
@@ -92,7 +90,8 @@ private abstract class FirToConstantValueTransformer(
|
|||||||
annotation: FirAnnotation,
|
annotation: FirAnnotation,
|
||||||
data: FirSession
|
data: FirSession
|
||||||
): ConstantValue<*> {
|
): ConstantValue<*> {
|
||||||
return AnnotationValue(annotation)
|
val mapping = annotation.argumentMapping.mapping.convertToConstantValues(data)
|
||||||
|
return AnnotationValue.create(annotation.annotationTypeRef.coneType, mapping)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: FirSession): ConstantValue<*> {
|
override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: FirSession): ConstantValue<*> {
|
||||||
@@ -103,7 +102,7 @@ private abstract class FirToConstantValueTransformer(
|
|||||||
getClassCall: FirGetClassCall,
|
getClassCall: FirGetClassCall,
|
||||||
data: FirSession
|
data: FirSession
|
||||||
): ConstantValue<*>? {
|
): ConstantValue<*>? {
|
||||||
return KClassValue.create(getClassCall.argument.typeRef.coneTypeUnsafe())
|
return create(getClassCall.argument.typeRef.coneTypeUnsafe())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitQualifiedAccessExpression(
|
override fun visitQualifiedAccessExpression(
|
||||||
@@ -136,20 +135,8 @@ private abstract class FirToConstantValueTransformer(
|
|||||||
val constructedClassSymbol = symbol.containingClassLookupTag()?.toFirRegularClassSymbol(data) ?: return null
|
val constructedClassSymbol = symbol.containingClassLookupTag()?.toFirRegularClassSymbol(data) ?: return null
|
||||||
if (constructedClassSymbol.classKind != ClassKind.ANNOTATION_CLASS) return null
|
if (constructedClassSymbol.classKind != ClassKind.ANNOTATION_CLASS) return null
|
||||||
|
|
||||||
return AnnotationValue(
|
val mapping = constructorCall.resolvedArgumentMapping?.convertToConstantValues(data) ?: return null
|
||||||
buildAnnotationCall {
|
return AnnotationValue.create(qualifiedAccessExpression.typeRef.coneType, mapping)
|
||||||
argumentMapping = buildAnnotationArgumentMapping {
|
|
||||||
constructorCall.resolvedArgumentMapping?.forEach { (firExpression, firValueParameter) ->
|
|
||||||
mapping[firValueParameter.name] = firExpression
|
|
||||||
}
|
|
||||||
}
|
|
||||||
annotationTypeRef = qualifiedAccessExpression.typeRef
|
|
||||||
calleeReference = buildSimpleNamedReference {
|
|
||||||
source = qualifiedAccessExpression.source
|
|
||||||
name = qualifiedAccessExpression.calleeReference.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol.callableId.packageName.asString() == "kotlin" -> {
|
symbol.callableId.packageName.asString() == "kotlin" -> {
|
||||||
@@ -240,7 +227,7 @@ internal object FirToConstantValueChecker : FirDefaultVisitor<Boolean, FirSessio
|
|||||||
override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: FirSession): Boolean = true
|
override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: FirSession): Boolean = true
|
||||||
|
|
||||||
override fun visitGetClassCall(getClassCall: FirGetClassCall, data: FirSession): Boolean {
|
override fun visitGetClassCall(getClassCall: FirGetClassCall, data: FirSession): Boolean {
|
||||||
return KClassValue.create(getClassCall.argument.typeRef.coneTypeUnsafe()) != null
|
return create(getClassCall.argument.typeRef.coneTypeUnsafe()) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: FirSession): Boolean {
|
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: FirSession): Boolean {
|
||||||
|
|||||||
+3
-3
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2023 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.
|
* 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.fir.serialization.constant
|
package org.jetbrains.kotlin.constant
|
||||||
|
|
||||||
internal abstract class AnnotationArgumentVisitor<R, D> {
|
abstract class AnnotationArgumentVisitor<R, D> {
|
||||||
abstract fun visitLongValue(value: LongValue, data: D): R
|
abstract fun visitLongValue(value: LongValue, data: D): R
|
||||||
abstract fun visitIntValue(value: IntValue, data: D): R
|
abstract fun visitIntValue(value: IntValue, data: D): R
|
||||||
abstract fun visitErrorValue(value: ErrorValue, data: D): R
|
abstract fun visitErrorValue(value: ErrorValue, data: D): R
|
||||||
+40
-62
@@ -1,21 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2023 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.
|
* 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.fir.serialization.constant
|
package org.jetbrains.kotlin.constant
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.constants.ClassLiteralValue
|
import org.jetbrains.kotlin.resolve.constants.ClassLiteralValue
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
|
|
||||||
internal sealed class ConstantValue<out T>(open val value: T) {
|
// Note 1: can be combined with org.jetbrains.kotlin.resolve.constants.ConstantValue but where is some questions to `AnnotationValue`.
|
||||||
|
// Note 2: if we are not going to implement previous idea, then this class can be moved to `fir` module.
|
||||||
|
// The problem here is that `ConstantValue` somehow must be accessible to `EvaluatedConstTracker`
|
||||||
|
// which in turn must be accessible to `CommonConfigurationKeys`.
|
||||||
|
sealed class ConstantValue<out T>(open val value: T) {
|
||||||
abstract fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R
|
abstract fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean = this === other || value == (other as? ConstantValue<*>)?.value
|
override fun equals(other: Any?): Boolean = this === other || value == (other as? ConstantValue<*>)?.value
|
||||||
@@ -27,30 +26,40 @@ internal sealed class ConstantValue<out T>(open val value: T) {
|
|||||||
open fun stringTemplateValue(): String = value.toString()
|
open fun stringTemplateValue(): String = value.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract class IntegerValueConstant<out T> protected constructor(value: T) : ConstantValue<T>(value)
|
abstract class IntegerValueConstant<out T> protected constructor(value: T) : ConstantValue<T>(value)
|
||||||
internal abstract class UnsignedValueConstant<out T> protected constructor(value: T) : ConstantValue<T>(value)
|
abstract class UnsignedValueConstant<out T> protected constructor(value: T) : ConstantValue<T>(value)
|
||||||
|
|
||||||
|
class AnnotationValue private constructor(value: Value) : ConstantValue<AnnotationValue.Value>(value) {
|
||||||
|
class Value(val type: KotlinTypeMarker, val argumentsMapping: Map<Name, ConstantValue<*>?>)
|
||||||
|
|
||||||
internal class AnnotationValue(value: FirAnnotation) : ConstantValue<FirAnnotation>(value) {
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitAnnotationValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitAnnotationValue(this, data)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun create(type: KotlinTypeMarker, argumentsMapping: Map<Name, ConstantValue<*>?>): AnnotationValue {
|
||||||
|
return AnnotationValue(
|
||||||
|
Value(type, argumentsMapping)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ArrayValue(
|
class ArrayValue(
|
||||||
value: List<ConstantValue<*>>,
|
value: List<ConstantValue<*>>,
|
||||||
) : ConstantValue<List<ConstantValue<*>>>(value) {
|
) : ConstantValue<List<ConstantValue<*>>>(value) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitArrayValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitArrayValue(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class BooleanValue(value: Boolean) : ConstantValue<Boolean>(value) {
|
class BooleanValue(value: Boolean) : ConstantValue<Boolean>(value) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitBooleanValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitBooleanValue(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ByteValue(value: Byte) : IntegerValueConstant<Byte>(value) {
|
class ByteValue(value: Byte) : IntegerValueConstant<Byte>(value) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitByteValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitByteValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "$value.toByte()"
|
override fun toString(): String = "$value.toByte()"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class CharValue(value: Char) : IntegerValueConstant<Char>(value) {
|
class CharValue(value: Char) : IntegerValueConstant<Char>(value) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitCharValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitCharValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "\\u%04X ('%s')".format(value.code, getPrintablePart(value))
|
override fun toString(): String = "\\u%04X ('%s')".format(value.code, getPrintablePart(value))
|
||||||
@@ -76,13 +85,13 @@ internal class CharValue(value: Char) : IntegerValueConstant<Char>(value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DoubleValue(value: Double) : ConstantValue<Double>(value) {
|
class DoubleValue(value: Double) : ConstantValue<Double>(value) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitDoubleValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitDoubleValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "$value.toDouble()"
|
override fun toString(): String = "$value.toDouble()"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class EnumValue(
|
class EnumValue(
|
||||||
val enumClassId: ClassId,
|
val enumClassId: ClassId,
|
||||||
val enumEntryName: Name
|
val enumEntryName: Name
|
||||||
) : ConstantValue<Pair<ClassId, Name>>(enumClassId to enumEntryName) {
|
) : ConstantValue<Pair<ClassId, Name>>(enumClassId to enumEntryName) {
|
||||||
@@ -91,7 +100,7 @@ internal class EnumValue(
|
|||||||
override fun toString(): String = "${enumClassId.shortClassName}.$enumEntryName"
|
override fun toString(): String = "${enumClassId.shortClassName}.$enumEntryName"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract class ErrorValue : ConstantValue<Unit>(Unit) {
|
abstract class ErrorValue : ConstantValue<Unit>(Unit) {
|
||||||
@Deprecated("Should not be called, for this is not a real value, but a indication of an error", level = DeprecationLevel.HIDDEN)
|
@Deprecated("Should not be called, for this is not a real value, but a indication of an error", level = DeprecationLevel.HIDDEN)
|
||||||
override val value: Unit
|
override val value: Unit
|
||||||
get() = throw UnsupportedOperationException()
|
get() = throw UnsupportedOperationException()
|
||||||
@@ -109,87 +118,56 @@ internal abstract class ErrorValue : ConstantValue<Unit>(Unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class FloatValue(value: Float) : ConstantValue<Float>(value) {
|
class FloatValue(value: Float) : ConstantValue<Float>(value) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitFloatValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitFloatValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "$value.toFloat()"
|
override fun toString(): String = "$value.toFloat()"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class IntValue(value: Int) : IntegerValueConstant<Int>(value) {
|
class IntValue(value: Int) : IntegerValueConstant<Int>(value) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitIntValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitIntValue(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class KClassValue(value: Value) : ConstantValue<KClassValue.Value>(value) {
|
class KClassValue private constructor(value: Value) : ConstantValue<KClassValue.Value>(value) {
|
||||||
sealed class Value {
|
sealed class Value {
|
||||||
data class NormalClass(val value: ClassLiteralValue) : Value() {
|
data class NormalClass(val value: ClassLiteralValue) : Value() {
|
||||||
val classId: ClassId get() = value.classId
|
val classId: ClassId get() = value.classId
|
||||||
val arrayDimensions: Int get() = value.arrayNestedness
|
val arrayDimensions: Int get() = value.arrayNestedness
|
||||||
}
|
}
|
||||||
|
|
||||||
data class LocalClass(val type: ConeKotlinType) : Value()
|
data class LocalClass(val type: KotlinTypeMarker) : Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(value: ClassLiteralValue) : this(Value.NormalClass(value))
|
constructor(value: ClassLiteralValue) : this(Value.NormalClass(value))
|
||||||
|
|
||||||
constructor(classId: ClassId, arrayDimensions: Int) : this(ClassLiteralValue(classId, arrayDimensions))
|
constructor(classId: ClassId, arrayDimensions: Int) : this(ClassLiteralValue(classId, arrayDimensions))
|
||||||
|
|
||||||
fun getArgumentType(session: FirSession): ConeKotlinType? {
|
|
||||||
when (value) {
|
|
||||||
is Value.LocalClass -> return value.type
|
|
||||||
is Value.NormalClass -> {
|
|
||||||
val (classId, arrayDimensions) = value.value
|
|
||||||
val klass = session.symbolProvider.getClassLikeSymbolByClassId(classId)?.fir as? FirRegularClass ?: return null
|
|
||||||
var type: ConeClassLikeType = klass.defaultType().replaceArgumentsWithStarProjections()
|
|
||||||
repeat(arrayDimensions) {
|
|
||||||
type = type.createArrayType()
|
|
||||||
}
|
|
||||||
return type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitKClassValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitKClassValue(this, data)
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun create(argumentType: ConeKotlinType): ConstantValue<*>? {
|
|
||||||
if (argumentType is ConeErrorType) return null
|
|
||||||
if (argumentType !is ConeClassLikeType) return null
|
|
||||||
var type = argumentType
|
|
||||||
var arrayDimensions = 0
|
|
||||||
while (true) {
|
|
||||||
if (type.isPrimitiveArray) break
|
|
||||||
type = type.arrayElementType() ?: break
|
|
||||||
arrayDimensions++
|
|
||||||
}
|
|
||||||
val classId = type.classId ?: return null
|
|
||||||
return KClassValue(classId, arrayDimensions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class LongValue(value: Long) : IntegerValueConstant<Long>(value) {
|
class LongValue(value: Long) : IntegerValueConstant<Long>(value) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitLongValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitLongValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "$value.toLong()"
|
override fun toString(): String = "$value.toLong()"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object NullValue : ConstantValue<Nothing?>(null) {
|
object NullValue : ConstantValue<Nothing?>(null) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitNullValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitNullValue(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ShortValue(value: Short) : IntegerValueConstant<Short>(value) {
|
class ShortValue(value: Short) : IntegerValueConstant<Short>(value) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitShortValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitShortValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "$value.toShort()"
|
override fun toString(): String = "$value.toShort()"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class StringValue(value: String) : ConstantValue<String>(value) {
|
class StringValue(value: String) : ConstantValue<String>(value) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitStringValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitStringValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "\"$value\""
|
override fun toString(): String = "\"$value\""
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class UByteValue(byteValue: Byte) : UnsignedValueConstant<Byte>(byteValue) {
|
class UByteValue(byteValue: Byte) : UnsignedValueConstant<Byte>(byteValue) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUByteValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUByteValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "$value.toUByte()"
|
override fun toString(): String = "$value.toUByte()"
|
||||||
@@ -197,7 +175,7 @@ internal class UByteValue(byteValue: Byte) : UnsignedValueConstant<Byte>(byteVal
|
|||||||
override fun stringTemplateValue(): String = (value.toInt() and 0xFF).toString()
|
override fun stringTemplateValue(): String = (value.toInt() and 0xFF).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class UShortValue(shortValue: Short) : UnsignedValueConstant<Short>(shortValue) {
|
class UShortValue(shortValue: Short) : UnsignedValueConstant<Short>(shortValue) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUShortValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUShortValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "$value.toUShort()"
|
override fun toString(): String = "$value.toUShort()"
|
||||||
@@ -205,7 +183,7 @@ internal class UShortValue(shortValue: Short) : UnsignedValueConstant<Short>(sho
|
|||||||
override fun stringTemplateValue(): String = (value.toInt() and 0xFFFF).toString()
|
override fun stringTemplateValue(): String = (value.toInt() and 0xFFFF).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class UIntValue(intValue: Int) : UnsignedValueConstant<Int>(intValue) {
|
class UIntValue(intValue: Int) : UnsignedValueConstant<Int>(intValue) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUIntValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUIntValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "$value.toUInt()"
|
override fun toString(): String = "$value.toUInt()"
|
||||||
@@ -213,7 +191,7 @@ internal class UIntValue(intValue: Int) : UnsignedValueConstant<Int>(intValue) {
|
|||||||
override fun stringTemplateValue(): String = (value.toLong() and 0xFFFFFFFFL).toString()
|
override fun stringTemplateValue(): String = (value.toLong() and 0xFFFFFFFFL).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ULongValue(longValue: Long) : UnsignedValueConstant<Long>(longValue) {
|
class ULongValue(longValue: Long) : UnsignedValueConstant<Long>(longValue) {
|
||||||
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitULongValue(this, data)
|
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitULongValue(this, data)
|
||||||
|
|
||||||
override fun toString(): String = "$value.toULong()"
|
override fun toString(): String = "$value.toULong()"
|
||||||
Reference in New Issue
Block a user