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.FirVariable
|
||||
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.deserializeClassToSymbol
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
@@ -112,6 +113,10 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
val (kotlinJvmBinaryClass, byteContent) =
|
||||
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 data = header.data ?: header.incompatibleData ?: return@mapNotNull null
|
||||
val strings = header.strings ?: return@mapNotNull null
|
||||
@@ -127,6 +132,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
FirDeserializationContext.createForPackage(
|
||||
packageFqName, packageProto, nameResolver, session,
|
||||
JvmBinaryAnnotationDeserializer(session, kotlinJvmBinaryClass, byteContent),
|
||||
FirConstDeserializer(session, kotlinJvmBinaryClass, facadeBinaryClass),
|
||||
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.impl.ConeClassLikeTypeImpl
|
||||
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.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
@@ -81,6 +82,7 @@ fun deserializeClassToSymbol(
|
||||
) ?: FirDeserializationContext.createForClass(
|
||||
classId, classProto, nameResolver, session,
|
||||
defaultAnnotationDeserializer ?: FirBuiltinAnnotationDeserializer(session),
|
||||
FirConstDeserializer(session, (containerSource as? KotlinJvmBinarySourceElement)?.binaryClass),
|
||||
containerSource
|
||||
)
|
||||
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 typeDeserializer: FirTypeDeserializer,
|
||||
val annotationDeserializer: AbstractAnnotationDeserializer,
|
||||
val constDeserializer: FirConstDeserializer,
|
||||
val containerSource: DeserializedContainerSource?,
|
||||
outerTypeParameters: List<FirTypeParameterSymbol>,
|
||||
val components: FirDeserializationComponents
|
||||
@@ -58,7 +59,8 @@ class FirDeserializationContext(
|
||||
FirTypeDeserializer(
|
||||
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)
|
||||
@@ -70,12 +72,14 @@ class FirDeserializationContext(
|
||||
nameResolver: NameResolver,
|
||||
session: FirSession,
|
||||
annotationDeserializer: AbstractAnnotationDeserializer,
|
||||
constDeserializer: FirConstDeserializer,
|
||||
containerSource: DeserializedContainerSource?
|
||||
) = createRootContext(
|
||||
nameResolver,
|
||||
TypeTable(packageProto.typeTable),
|
||||
session,
|
||||
annotationDeserializer,
|
||||
constDeserializer,
|
||||
fqName,
|
||||
relativeClassName = null,
|
||||
typeParameterProtos = emptyList(),
|
||||
@@ -88,12 +92,14 @@ class FirDeserializationContext(
|
||||
nameResolver: NameResolver,
|
||||
session: FirSession,
|
||||
annotationDeserializer: AbstractAnnotationDeserializer,
|
||||
constDeserializer: FirConstDeserializer,
|
||||
containerSource: DeserializedContainerSource?
|
||||
) = createRootContext(
|
||||
nameResolver,
|
||||
TypeTable(classProto.typeTable),
|
||||
session,
|
||||
annotationDeserializer,
|
||||
constDeserializer,
|
||||
classId.packageFqName,
|
||||
classId.relativeClassName,
|
||||
classProto.typeParameterList,
|
||||
@@ -105,6 +111,7 @@ class FirDeserializationContext(
|
||||
typeTable: TypeTable,
|
||||
session: FirSession,
|
||||
annotationDeserializer: AbstractAnnotationDeserializer,
|
||||
constDeserializer: FirConstDeserializer,
|
||||
packageFqName: FqName,
|
||||
relativeClassName: FqName?,
|
||||
typeParameterProtos: List<ProtoBuf.TypeParameter>,
|
||||
@@ -124,6 +131,7 @@ class FirDeserializationContext(
|
||||
null
|
||||
),
|
||||
annotationDeserializer,
|
||||
constDeserializer,
|
||||
containerSource,
|
||||
emptyList(),
|
||||
FirDeserializationComponents()
|
||||
@@ -272,11 +280,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
this.getter = getter
|
||||
this.setter = setter
|
||||
this.containerSource = c.containerSource
|
||||
this.initializer = if (Flags.HAS_CONSTANT.get(flags)) {
|
||||
proto.getExtensionOrNull(BuiltInSerializerProtocol.compileTimeValue)?.let {
|
||||
c.annotationDeserializer.resolveValue(returnTypeRef, it, c.nameResolver)
|
||||
}
|
||||
} else null
|
||||
this.initializer = c.constDeserializer.loadConstant(proto, symbol.callableId, c.nameResolver)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+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.impl.FirDeclarationStatusImpl
|
||||
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.deserializeClassToSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
@@ -78,6 +79,7 @@ class FirBuiltinSymbolProvider(val session: FirSession, val kotlinScopeProvider:
|
||||
FirDeserializationContext.createForPackage(
|
||||
fqName, packageProto.`package`, nameResolver, session,
|
||||
FirBuiltinAnnotationDeserializer(session),
|
||||
FirConstDeserializer(session),
|
||||
containerSource = null
|
||||
).memberDeserializer
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user