Implement constant deserializer for fir
This deserializer is uniform loader, that is responsible for loading all constants. For example, Math.E, UInt.MAX_VALUE or Float.MIN_VALUE.
This commit is contained in:
+6
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl
|
import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl
|
||||||
|
import org.jetbrains.kotlin.fir.deserialization.FirConstDeserializer
|
||||||
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
|
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
|
||||||
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
|
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||||
@@ -112,6 +113,10 @@ class KotlinDeserializedJvmSymbolsProvider(
|
|||||||
val (kotlinJvmBinaryClass, byteContent) =
|
val (kotlinJvmBinaryClass, byteContent) =
|
||||||
kotlinClassFinder.findKotlinClassOrContent(classId) as? KotlinClassFinder.Result.KotlinClass ?: return@mapNotNull null
|
kotlinClassFinder.findKotlinClassOrContent(classId) as? KotlinClassFinder.Result.KotlinClass ?: return@mapNotNull null
|
||||||
|
|
||||||
|
val facadeName = kotlinJvmBinaryClass.classHeader.multifileClassName?.takeIf { it.isNotEmpty() }
|
||||||
|
val facadeFqName = facadeName?.let { JvmClassName.byInternalName(it).fqNameForTopLevelClassMaybeWithDollars }
|
||||||
|
val facadeBinaryClass = facadeFqName?.let { kotlinClassFinder.findKotlinClass(ClassId.topLevel(it)) }
|
||||||
|
|
||||||
val header = kotlinJvmBinaryClass.classHeader
|
val header = kotlinJvmBinaryClass.classHeader
|
||||||
val data = header.data ?: header.incompatibleData ?: return@mapNotNull null
|
val data = header.data ?: header.incompatibleData ?: return@mapNotNull null
|
||||||
val strings = header.strings ?: return@mapNotNull null
|
val strings = header.strings ?: return@mapNotNull null
|
||||||
@@ -127,6 +132,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
|||||||
FirDeserializationContext.createForPackage(
|
FirDeserializationContext.createForPackage(
|
||||||
packageFqName, packageProto, nameResolver, session,
|
packageFqName, packageProto, nameResolver, session,
|
||||||
JvmBinaryAnnotationDeserializer(session, kotlinJvmBinaryClass, byteContent),
|
JvmBinaryAnnotationDeserializer(session, kotlinJvmBinaryClass, byteContent),
|
||||||
|
FirConstDeserializer(session, kotlinJvmBinaryClass, facadeBinaryClass),
|
||||||
source
|
source
|
||||||
),
|
),
|
||||||
source,
|
source,
|
||||||
|
|||||||
+2
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
|||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||||
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
|
||||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||||
@@ -81,6 +82,7 @@ fun deserializeClassToSymbol(
|
|||||||
) ?: FirDeserializationContext.createForClass(
|
) ?: FirDeserializationContext.createForClass(
|
||||||
classId, classProto, nameResolver, session,
|
classId, classProto, nameResolver, session,
|
||||||
defaultAnnotationDeserializer ?: FirBuiltinAnnotationDeserializer(session),
|
defaultAnnotationDeserializer ?: FirBuiltinAnnotationDeserializer(session),
|
||||||
|
FirConstDeserializer(session, (containerSource as? KotlinJvmBinarySourceElement)?.binaryClass),
|
||||||
containerSource
|
containerSource
|
||||||
)
|
)
|
||||||
buildRegularClass {
|
buildRegularClass {
|
||||||
|
|||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* 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.deserialization
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirConstKind
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||||
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
|
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||||
|
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||||
|
import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||||
|
|
||||||
|
class FirConstDeserializer(
|
||||||
|
val session: FirSession,
|
||||||
|
private val partSource: KotlinJvmBinaryClass? = null,
|
||||||
|
private val facadeSource: KotlinJvmBinaryClass? = null
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
private val constantCache = mutableMapOf<CallableId, FirExpression>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadConstant(propertyProto: ProtoBuf.Property, callableId: CallableId, nameResolver: NameResolver): FirExpression? {
|
||||||
|
if (!Flags.HAS_CONSTANT.get(propertyProto.flags)) return null
|
||||||
|
|
||||||
|
constantCache[callableId]?.let { return it }
|
||||||
|
|
||||||
|
if (facadeSource == null && partSource == null) {
|
||||||
|
val value = propertyProto.getExtensionOrNull(BuiltInSerializerProtocol.compileTimeValue) ?: return null
|
||||||
|
return buildFirConstant(value, null, value.type.name, nameResolver)?.apply { constantCache[callableId] = this }
|
||||||
|
}
|
||||||
|
|
||||||
|
(facadeSource ?: partSource)!!.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor {
|
||||||
|
override fun visitMethod(name: Name, desc: String): KotlinJvmBinaryClass.MethodAnnotationVisitor? = null
|
||||||
|
|
||||||
|
override fun visitField(name: Name, desc: String, initializer: Any?): KotlinJvmBinaryClass.AnnotationVisitor? {
|
||||||
|
if (initializer != null) {
|
||||||
|
val constant = buildFirConstant(null, initializer, desc, nameResolver)
|
||||||
|
constant?.let { constantCache[callableId.replaceName(name)] = it }
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}, null)
|
||||||
|
|
||||||
|
return constantCache[callableId]
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildFirConstant(
|
||||||
|
protoValue: ProtoBuf.Annotation.Argument.Value?, sourceValue: Any?, constKind: String, nameResolver: NameResolver
|
||||||
|
): FirExpression? {
|
||||||
|
return when (constKind) {
|
||||||
|
"BYTE", "B" -> buildConstExpression(null, FirConstKind.Byte, ((protoValue?.intValue ?: sourceValue) as Number).toByte())
|
||||||
|
"CHAR", "C" -> buildConstExpression(null, FirConstKind.Char, ((protoValue?.intValue ?: sourceValue) as Number).toChar())
|
||||||
|
"SHORT", "S" -> buildConstExpression(null, FirConstKind.Short, ((protoValue?.intValue ?: sourceValue) as Number).toShort())
|
||||||
|
"INT", "I" -> buildConstExpression(null, FirConstKind.Int, protoValue?.intValue?.toInt() ?: sourceValue as Int)
|
||||||
|
"LONG", "J" -> buildConstExpression(null, FirConstKind.Long, (protoValue?.intValue ?: sourceValue) as Long)
|
||||||
|
"FLOAT", "F" -> buildConstExpression(null, FirConstKind.Float, (protoValue?.floatValue ?: sourceValue) as Float)
|
||||||
|
"DOUBLE", "D" -> buildConstExpression(null, FirConstKind.Double, (protoValue?.doubleValue ?: sourceValue) as Double)
|
||||||
|
"BOOLEAN", "Z" -> buildConstExpression(null, FirConstKind.Boolean, (protoValue?.intValue?.toInt() ?: sourceValue) != 0)
|
||||||
|
"STRING", "Ljava/lang/String" -> buildConstExpression(
|
||||||
|
null, FirConstKind.String, protoValue?.stringValue?.let { nameResolver.getString(it) } ?: sourceValue as String
|
||||||
|
)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun CallableId.replaceName(newName: Name): CallableId {
|
||||||
|
return CallableId(this.packageName, this.className, newName)
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-6
@@ -40,6 +40,7 @@ class FirDeserializationContext(
|
|||||||
val relativeClassName: FqName?,
|
val relativeClassName: FqName?,
|
||||||
val typeDeserializer: FirTypeDeserializer,
|
val typeDeserializer: FirTypeDeserializer,
|
||||||
val annotationDeserializer: AbstractAnnotationDeserializer,
|
val annotationDeserializer: AbstractAnnotationDeserializer,
|
||||||
|
val constDeserializer: FirConstDeserializer,
|
||||||
val containerSource: DeserializedContainerSource?,
|
val containerSource: DeserializedContainerSource?,
|
||||||
outerTypeParameters: List<FirTypeParameterSymbol>,
|
outerTypeParameters: List<FirTypeParameterSymbol>,
|
||||||
val components: FirDeserializationComponents
|
val components: FirDeserializationComponents
|
||||||
@@ -58,7 +59,8 @@ class FirDeserializationContext(
|
|||||||
FirTypeDeserializer(
|
FirTypeDeserializer(
|
||||||
session, nameResolver, typeTable, typeParameterProtos, typeDeserializer
|
session, nameResolver, typeTable, typeParameterProtos, typeDeserializer
|
||||||
),
|
),
|
||||||
annotationDeserializer, containerSource, if (capturesTypeParameters) allTypeParameters else emptyList(), components
|
annotationDeserializer, constDeserializer, containerSource,
|
||||||
|
if (capturesTypeParameters) allTypeParameters else emptyList(), components
|
||||||
)
|
)
|
||||||
|
|
||||||
val memberDeserializer: FirMemberDeserializer = FirMemberDeserializer(this)
|
val memberDeserializer: FirMemberDeserializer = FirMemberDeserializer(this)
|
||||||
@@ -70,12 +72,14 @@ class FirDeserializationContext(
|
|||||||
nameResolver: NameResolver,
|
nameResolver: NameResolver,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
annotationDeserializer: AbstractAnnotationDeserializer,
|
annotationDeserializer: AbstractAnnotationDeserializer,
|
||||||
|
constDeserializer: FirConstDeserializer,
|
||||||
containerSource: DeserializedContainerSource?
|
containerSource: DeserializedContainerSource?
|
||||||
) = createRootContext(
|
) = createRootContext(
|
||||||
nameResolver,
|
nameResolver,
|
||||||
TypeTable(packageProto.typeTable),
|
TypeTable(packageProto.typeTable),
|
||||||
session,
|
session,
|
||||||
annotationDeserializer,
|
annotationDeserializer,
|
||||||
|
constDeserializer,
|
||||||
fqName,
|
fqName,
|
||||||
relativeClassName = null,
|
relativeClassName = null,
|
||||||
typeParameterProtos = emptyList(),
|
typeParameterProtos = emptyList(),
|
||||||
@@ -88,12 +92,14 @@ class FirDeserializationContext(
|
|||||||
nameResolver: NameResolver,
|
nameResolver: NameResolver,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
annotationDeserializer: AbstractAnnotationDeserializer,
|
annotationDeserializer: AbstractAnnotationDeserializer,
|
||||||
|
constDeserializer: FirConstDeserializer,
|
||||||
containerSource: DeserializedContainerSource?
|
containerSource: DeserializedContainerSource?
|
||||||
) = createRootContext(
|
) = createRootContext(
|
||||||
nameResolver,
|
nameResolver,
|
||||||
TypeTable(classProto.typeTable),
|
TypeTable(classProto.typeTable),
|
||||||
session,
|
session,
|
||||||
annotationDeserializer,
|
annotationDeserializer,
|
||||||
|
constDeserializer,
|
||||||
classId.packageFqName,
|
classId.packageFqName,
|
||||||
classId.relativeClassName,
|
classId.relativeClassName,
|
||||||
classProto.typeParameterList,
|
classProto.typeParameterList,
|
||||||
@@ -105,6 +111,7 @@ class FirDeserializationContext(
|
|||||||
typeTable: TypeTable,
|
typeTable: TypeTable,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
annotationDeserializer: AbstractAnnotationDeserializer,
|
annotationDeserializer: AbstractAnnotationDeserializer,
|
||||||
|
constDeserializer: FirConstDeserializer,
|
||||||
packageFqName: FqName,
|
packageFqName: FqName,
|
||||||
relativeClassName: FqName?,
|
relativeClassName: FqName?,
|
||||||
typeParameterProtos: List<ProtoBuf.TypeParameter>,
|
typeParameterProtos: List<ProtoBuf.TypeParameter>,
|
||||||
@@ -124,6 +131,7 @@ class FirDeserializationContext(
|
|||||||
null
|
null
|
||||||
),
|
),
|
||||||
annotationDeserializer,
|
annotationDeserializer,
|
||||||
|
constDeserializer,
|
||||||
containerSource,
|
containerSource,
|
||||||
emptyList(),
|
emptyList(),
|
||||||
FirDeserializationComponents()
|
FirDeserializationComponents()
|
||||||
@@ -272,11 +280,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
|||||||
this.getter = getter
|
this.getter = getter
|
||||||
this.setter = setter
|
this.setter = setter
|
||||||
this.containerSource = c.containerSource
|
this.containerSource = c.containerSource
|
||||||
this.initializer = if (Flags.HAS_CONSTANT.get(flags)) {
|
this.initializer = c.constDeserializer.loadConstant(proto, symbol.callableId, c.nameResolver)
|
||||||
proto.getExtensionOrNull(BuiltInSerializerProtocol.compileTimeValue)?.let {
|
|
||||||
c.annotationDeserializer.resolveValue(returnTypeRef, it, c.nameResolver)
|
|
||||||
}
|
|
||||||
} else null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildTypeParameter
|
|||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
||||||
import org.jetbrains.kotlin.fir.deserialization.FirBuiltinAnnotationDeserializer
|
import org.jetbrains.kotlin.fir.deserialization.FirBuiltinAnnotationDeserializer
|
||||||
|
import org.jetbrains.kotlin.fir.deserialization.FirConstDeserializer
|
||||||
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
|
import org.jetbrains.kotlin.fir.deserialization.FirDeserializationContext
|
||||||
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
|
import org.jetbrains.kotlin.fir.deserialization.deserializeClassToSymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||||
@@ -78,6 +79,7 @@ class FirBuiltinSymbolProvider(val session: FirSession, val kotlinScopeProvider:
|
|||||||
FirDeserializationContext.createForPackage(
|
FirDeserializationContext.createForPackage(
|
||||||
fqName, packageProto.`package`, nameResolver, session,
|
fqName, packageProto.`package`, nameResolver, session,
|
||||||
FirBuiltinAnnotationDeserializer(session),
|
FirBuiltinAnnotationDeserializer(session),
|
||||||
|
FirConstDeserializer(session),
|
||||||
containerSource = null
|
containerSource = null
|
||||||
).memberDeserializer
|
).memberDeserializer
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user