From d2a89423536b585c75f3d7632fa3545c86048e02 Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Fri, 17 Dec 2021 18:15:18 +0300 Subject: [PATCH] [FIR] Extract FirJvmConstDeserializer Attempts to separate JVM and non-JVM entities more clearly. --- .../deserialization/ClassDeserialization.kt | 10 ++- .../deserialization/FirConstDeserializer.kt | 74 +++++++------------ .../FirJvmConstDeserializer.kt | 39 ++++++++++ .../JvmClassFileBasedSymbolProvider.kt | 2 +- 4 files changed, 75 insertions(+), 50 deletions(-) create mode 100644 compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirJvmConstDeserializer.kt diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt index 03e201df320..2a80ffba220 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt @@ -67,6 +67,12 @@ fun deserializeClassToSymbol( } val isSealed = modality == Modality.SEALED val annotationDeserializer = defaultAnnotationDeserializer ?: FirBuiltinAnnotationDeserializer(session) + val jvmBinaryClass = (containerSource as? KotlinJvmBinarySourceElement)?.binaryClass + val constDeserializer = if (jvmBinaryClass != null) { + FirJvmConstDeserializer(session, jvmBinaryClass) + } else { + FirConstDeserializer(session) + } val context = parentContext?.childContext( classProto.typeParameterList, @@ -79,7 +85,7 @@ fun deserializeClassToSymbol( if (status.isCompanion) { parentContext.constDeserializer } else { - ((containerSource as? KotlinJvmBinarySourceElement)?.binaryClass)?.let { FirConstDeserializer(session, it) } + ((containerSource as? KotlinJvmBinarySourceElement)?.binaryClass)?.let { FirJvmConstDeserializer(session, it) } ?: parentContext.constDeserializer }, status.isInner @@ -89,7 +95,7 @@ fun deserializeClassToSymbol( nameResolver, moduleData, annotationDeserializer, - FirConstDeserializer(session, (containerSource as? KotlinJvmBinarySourceElement)?.binaryClass), + constDeserializer, containerSource, symbol ) diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirConstDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirConstDeserializer.kt index b3b0adfaafc..3db52933f96 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirConstDeserializer.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirConstDeserializer.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression import org.jetbrains.kotlin.name.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 @@ -18,57 +17,38 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol import org.jetbrains.kotlin.types.ConstantValueKind -class FirConstDeserializer( - val session: FirSession, - private val binaryClass: KotlinJvmBinaryClass? = null +open class FirConstDeserializer( + val session: FirSession ) { - private val constantCache = mutableMapOf() + protected val constantCache = mutableMapOf() - fun loadConstant(propertyProto: ProtoBuf.Property, callableId: CallableId, nameResolver: NameResolver): FirExpression? { + open 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 (binaryClass == null) { - val value = propertyProto.getExtensionOrNull(BuiltInSerializerProtocol.compileTimeValue) ?: return null - return buildFirConstant(value, null, value.type.name, nameResolver)?.apply { constantCache[callableId] = this } - } - - binaryClass.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] + val value = propertyProto.getExtensionOrNull(BuiltInSerializerProtocol.compileTimeValue) ?: return null + return buildFirConstant(value, null, value.type.name, nameResolver)?.also { constantCache[callableId] = it } } +} - private fun buildFirConstant( - protoValue: ProtoBuf.Annotation.Argument.Value?, sourceValue: Any?, constKind: String, nameResolver: NameResolver - ): FirExpression? { - return when (constKind) { - "BYTE", "B" -> buildConstExpression(null, ConstantValueKind.Byte, ((protoValue?.intValue ?: sourceValue) as Number).toByte()) - "CHAR", "C" -> buildConstExpression(null, ConstantValueKind.Char, ((protoValue?.intValue ?: sourceValue) as Number).toInt().toChar()) - "SHORT", "S" -> buildConstExpression(null, ConstantValueKind.Short, ((protoValue?.intValue ?: sourceValue) as Number).toShort()) - "INT", "I" -> buildConstExpression(null, ConstantValueKind.Int, protoValue?.intValue?.toInt() ?: sourceValue as Int) - "LONG", "J" -> buildConstExpression(null, ConstantValueKind.Long, protoValue?.intValue ?: sourceValue as Long) - "FLOAT", "F" -> buildConstExpression(null, ConstantValueKind.Float, protoValue?.floatValue ?: sourceValue as Float) - "DOUBLE", "D" -> buildConstExpression(null, ConstantValueKind.Double, protoValue?.doubleValue ?: sourceValue as Double) - "BOOLEAN", "Z" -> buildConstExpression(null, ConstantValueKind.Boolean, (protoValue?.intValue?.toInt() ?: sourceValue) != 0) - "STRING", "Ljava/lang/String;" -> buildConstExpression( - null, ConstantValueKind.String, protoValue?.stringValue?.let { nameResolver.getString(it) } ?: sourceValue as String - ) - else -> null - } +fun buildFirConstant( + protoValue: ProtoBuf.Annotation.Argument.Value?, sourceValue: Any?, constKind: String, nameResolver: NameResolver +): FirExpression? { + return when (constKind) { + "BYTE", "B" -> buildConstExpression(null, ConstantValueKind.Byte, ((protoValue?.intValue ?: sourceValue) as Number).toByte()) + "CHAR", "C" -> buildConstExpression(null, ConstantValueKind.Char, ((protoValue?.intValue ?: sourceValue) as Number).toInt().toChar()) + "SHORT", "S" -> buildConstExpression(null, ConstantValueKind.Short, ((protoValue?.intValue ?: sourceValue) as Number).toShort()) + "INT", "I" -> buildConstExpression(null, ConstantValueKind.Int, protoValue?.intValue?.toInt() ?: sourceValue as Int) + "LONG", "J" -> buildConstExpression(null, ConstantValueKind.Long, protoValue?.intValue ?: sourceValue as Long) + "FLOAT", "F" -> buildConstExpression(null, ConstantValueKind.Float, protoValue?.floatValue ?: sourceValue as Float) + "DOUBLE", "D" -> buildConstExpression(null, ConstantValueKind.Double, protoValue?.doubleValue ?: sourceValue as Double) + "BOOLEAN", "Z" -> buildConstExpression(null, ConstantValueKind.Boolean, (protoValue?.intValue?.toInt() ?: sourceValue) != 0) + "STRING", "Ljava/lang/String;" -> buildConstExpression( + null, ConstantValueKind.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) - } -} \ No newline at end of file +fun CallableId.replaceName(newName: Name): CallableId { + return CallableId(this.packageName, this.className, newName) +} diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirJvmConstDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirJvmConstDeserializer.kt new file mode 100644 index 00000000000..ead1c7ae6a4 --- /dev/null +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirJvmConstDeserializer.kt @@ -0,0 +1,39 @@ +/* + * 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.FirExpression +import org.jetbrains.kotlin.name.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.name.Name + +class FirJvmConstDeserializer( + session: FirSession, + private val binaryClass: KotlinJvmBinaryClass, +) : FirConstDeserializer(session) { + override fun loadConstant(propertyProto: ProtoBuf.Property, callableId: CallableId, nameResolver: NameResolver): FirExpression? { + if (!Flags.HAS_CONSTANT.get(propertyProto.flags)) return null + constantCache[callableId]?.let { return it } + + binaryClass.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] + } +} \ No newline at end of file diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmClassFileBasedSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmClassFileBasedSymbolProvider.kt index 9abda63924e..a49258a523f 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmClassFileBasedSymbolProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmClassFileBasedSymbolProvider.kt @@ -81,7 +81,7 @@ class JvmClassFileBasedSymbolProvider( FirDeserializationContext.createForPackage( packageFqName, packageProto, nameResolver, moduleData, JvmBinaryAnnotationDeserializer(session, kotlinJvmBinaryClass, kotlinClassFinder, byteContent), - FirConstDeserializer(session, facadeBinaryClass ?: kotlinJvmBinaryClass), + FirJvmConstDeserializer(session, facadeBinaryClass ?: kotlinJvmBinaryClass), source ), )