[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:
Ivan Kylchik
2023-04-05 23:00:50 +02:00
committed by Space Team
parent fe989d0ba7
commit 297b6ae64b
7 changed files with 163 additions and 117 deletions
@@ -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++
@@ -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 {
@@ -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
@@ -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)
}
@@ -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 {
@@ -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
@@ -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()"