[FIR] Move deserialization files to module :compiler:fir:fir-deserialization
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":core:descriptors"))
|
||||
implementation(project(":core:descriptors.jvm"))
|
||||
implementation(project(":core:deserialization"))
|
||||
|
||||
api(project(":compiler:fir:cones"))
|
||||
api(project(":compiler:fir:tree"))
|
||||
api(project(":compiler:fir:resolve"))
|
||||
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { none() }
|
||||
}
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* 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.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.collectEnumEntries
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations
|
||||
import org.jetbrains.kotlin.fir.resolve.constructType
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedSymbolError
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.constructType
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf.Annotation.Argument.Value.Type.*
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
|
||||
abstract class AbstractAnnotationDeserializer(
|
||||
private val session: FirSession
|
||||
) {
|
||||
protected val protocol = BuiltInSerializerProtocol
|
||||
|
||||
open fun inheritAnnotationInfo(parent: AbstractAnnotationDeserializer) {
|
||||
}
|
||||
|
||||
enum class CallableKind {
|
||||
PROPERTY,
|
||||
PROPERTY_GETTER,
|
||||
PROPERTY_SETTER,
|
||||
OTHERS
|
||||
}
|
||||
|
||||
fun loadClassAnnotations(classProto: ProtoBuf.Class, nameResolver: NameResolver): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(classProto.flags)) return emptyList()
|
||||
val annotations = classProto.getExtension(protocol.classAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
open fun loadFunctionAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
functionProto: ProtoBuf.Function,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(functionProto.flags)) return emptyList()
|
||||
val annotations = functionProto.getExtension(protocol.functionAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
open fun loadPropertyAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(propertyProto.flags)) return emptyList()
|
||||
val annotations = propertyProto.getExtension(protocol.propertyAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver, AnnotationUseSiteTarget.PROPERTY) }
|
||||
}
|
||||
|
||||
open fun loadPropertyBackingFieldAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
): List<FirAnnotationCall> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
open fun loadPropertyDelegatedFieldAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
): List<FirAnnotationCall> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
open fun loadPropertyGetterAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
getterFlags: Int
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(getterFlags)) return emptyList()
|
||||
val annotations = propertyProto.getExtension(protocol.propertyGetterAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver, AnnotationUseSiteTarget.PROPERTY_GETTER) }
|
||||
}
|
||||
|
||||
open fun loadPropertySetterAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
propertyProto: ProtoBuf.Property,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
setterFlags: Int
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(setterFlags)) return emptyList()
|
||||
val annotations = propertyProto.getExtension(protocol.propertySetterAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver, AnnotationUseSiteTarget.PROPERTY_SETTER) }
|
||||
}
|
||||
|
||||
open fun loadConstructorAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
constructorProto: ProtoBuf.Constructor,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(constructorProto.flags)) return emptyList()
|
||||
val annotations = constructorProto.getExtension(protocol.constructorAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
open fun loadValueParameterAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
callableProto: MessageLite,
|
||||
valueParameterProto: ProtoBuf.ValueParameter,
|
||||
classProto: ProtoBuf.Class?,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
kind: CallableKind,
|
||||
parameterIndex: Int
|
||||
): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(valueParameterProto.flags)) return emptyList()
|
||||
val annotations = valueParameterProto.getExtension(protocol.parameterAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
|
||||
open fun loadExtensionReceiverParameterAnnotations(
|
||||
containerSource: DeserializedContainerSource?,
|
||||
callableProto: MessageLite,
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
kind: CallableKind
|
||||
): List<FirAnnotationCall> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
abstract fun loadTypeAnnotations(typeProto: ProtoBuf.Type, nameResolver: NameResolver): List<FirAnnotationCall>
|
||||
|
||||
fun deserializeAnnotation(
|
||||
proto: ProtoBuf.Annotation,
|
||||
nameResolver: NameResolver,
|
||||
useSiteTarget: AnnotationUseSiteTarget? = null
|
||||
): FirAnnotationCall {
|
||||
val classId = nameResolver.getClassId(proto.id)
|
||||
val lookupTag = ConeClassLikeLookupTagImpl(classId)
|
||||
val symbol = lookupTag.toSymbol(session)
|
||||
val firAnnotationClass = (symbol as? FirRegularClassSymbol)?.fir
|
||||
|
||||
var arguments = emptyList<FirExpression>()
|
||||
if (proto.argumentCount != 0 && firAnnotationClass?.classKind == ClassKind.ANNOTATION_CLASS) {
|
||||
val constructor = firAnnotationClass.declarations.firstOrNull { it is FirConstructor }
|
||||
if (constructor is FirConstructor) {
|
||||
val parameterByName = constructor.valueParameters.associateBy { it.name }
|
||||
|
||||
arguments = proto.argumentList.mapNotNull {
|
||||
val name = nameResolver.getName(it.nameId)
|
||||
val parameter = parameterByName[name] ?: return@mapNotNull null
|
||||
val value = resolveValue(parameter.returnTypeRef, it.value, nameResolver) ?: return@mapNotNull null
|
||||
buildNamedArgumentExpression {
|
||||
expression = value
|
||||
isSpread = false
|
||||
this.name = name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buildAnnotationCall {
|
||||
annotationTypeRef = symbol?.let {
|
||||
buildResolvedTypeRef {
|
||||
type = it.constructType(emptyArray(), isNullable = false)
|
||||
}
|
||||
} ?: buildErrorTypeRef { diagnostic = ConeUnresolvedSymbolError(classId) }
|
||||
argumentList = buildArgumentList {
|
||||
this.arguments += arguments
|
||||
}
|
||||
useSiteTarget?.let {
|
||||
this.useSiteTarget = it
|
||||
}
|
||||
calleeReference = FirReferencePlaceholderForResolvedAnnotations
|
||||
}
|
||||
}
|
||||
|
||||
fun resolveValue(
|
||||
expectedType: FirTypeRef, value: ProtoBuf.Annotation.Argument.Value, nameResolver: NameResolver
|
||||
): FirExpression? {
|
||||
// TODO: val isUnsigned = Flags.IS_UNSIGNED.get(value.flags)
|
||||
|
||||
val result: FirExpression = when (value.type) {
|
||||
BYTE -> const(FirConstKind.Byte, value.intValue.toByte())
|
||||
CHAR -> const(FirConstKind.Char, value.intValue.toChar())
|
||||
SHORT -> const(FirConstKind.Short, value.intValue.toShort())
|
||||
INT -> const(FirConstKind.Int, value.intValue.toInt())
|
||||
LONG -> const(FirConstKind.Long, value.intValue)
|
||||
FLOAT -> const(FirConstKind.Float, value.floatValue)
|
||||
DOUBLE -> const(FirConstKind.Double, value.doubleValue)
|
||||
BOOLEAN -> const(FirConstKind.Boolean, (value.intValue != 0L))
|
||||
STRING -> const(FirConstKind.String, nameResolver.getString(value.stringValue))
|
||||
ANNOTATION -> deserializeAnnotation(value.annotation, nameResolver)
|
||||
CLASS -> buildGetClassCall {
|
||||
val classId = nameResolver.getClassId(value.classId)
|
||||
val lookupTag = ConeClassLikeLookupTagImpl(classId)
|
||||
val referencedType = lookupTag.constructType(emptyArray(), isNullable = false)
|
||||
argumentList = buildUnaryArgumentList(
|
||||
buildClassReferenceExpression {
|
||||
classTypeRef = buildResolvedTypeRef {
|
||||
type = referencedType
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
ENUM -> buildFunctionCall {
|
||||
val classId = nameResolver.getClassId(value.classId)
|
||||
val entryName = nameResolver.getName(value.enumValueId)
|
||||
|
||||
|
||||
val enumLookupTag = ConeClassLikeLookupTagImpl(classId)
|
||||
val enumSymbol = enumLookupTag.toSymbol(this@AbstractAnnotationDeserializer.session)
|
||||
val firClass = enumSymbol?.fir as? FirRegularClass
|
||||
val enumEntries = firClass?.collectEnumEntries() ?: emptyList()
|
||||
val enumEntrySymbol = enumEntries.find { it.name == entryName }
|
||||
this.calleeReference = enumEntrySymbol?.let {
|
||||
buildResolvedNamedReference {
|
||||
name = entryName
|
||||
resolvedSymbol = it.symbol
|
||||
}
|
||||
} ?: buildErrorNamedReference {
|
||||
diagnostic = ConeSimpleDiagnostic("Strange deserialized enum value: $classId.$entryName", DiagnosticKind.DeserializationError)
|
||||
}
|
||||
}
|
||||
// ARRAY -> {
|
||||
// TODO: see AnnotationDeserializer
|
||||
// }
|
||||
// else -> error("Unsupported annotation argument type: ${value.type} (expected $expectedType)")
|
||||
else -> return null
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun <T> const(kind: FirConstKind<T>, value: T) = buildConstExpression(null, kind, value)
|
||||
}
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* 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.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsSettings
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCloneableSymbolProvider.Companion.CLONE
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCloneableSymbolProvider.Companion.CLONEABLE_CLASS_ID
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.sealedInheritors
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeAttributes
|
||||
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
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.metadata.deserialization.supertypes
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
|
||||
fun deserializeClassToSymbol(
|
||||
classId: ClassId,
|
||||
classProto: ProtoBuf.Class,
|
||||
symbol: FirRegularClassSymbol,
|
||||
nameResolver: NameResolver,
|
||||
session: FirSession,
|
||||
defaultAnnotationDeserializer: AbstractAnnotationDeserializer?,
|
||||
scopeProvider: FirScopeProvider,
|
||||
parentContext: FirDeserializationContext? = null,
|
||||
containerSource: DeserializedContainerSource? = null,
|
||||
deserializeNestedClass: (ClassId, FirDeserializationContext) -> FirRegularClassSymbol?
|
||||
) {
|
||||
val flags = classProto.flags
|
||||
val kind = Flags.CLASS_KIND.get(flags)
|
||||
val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(flags))
|
||||
val status = FirResolvedDeclarationStatusImpl(
|
||||
FirProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)),
|
||||
modality
|
||||
).apply {
|
||||
isExpect = Flags.IS_EXPECT_CLASS.get(flags)
|
||||
isActual = false
|
||||
isCompanion = kind == ProtoBuf.Class.Kind.COMPANION_OBJECT
|
||||
isInner = Flags.IS_INNER.get(flags)
|
||||
isData = Flags.IS_DATA.get(classProto.flags)
|
||||
isInline = Flags.IS_INLINE_CLASS.get(classProto.flags)
|
||||
}
|
||||
val isSealed = modality == Modality.SEALED
|
||||
val annotationDeserializer = defaultAnnotationDeserializer ?: FirBuiltinAnnotationDeserializer(session)
|
||||
val context =
|
||||
parentContext?.childContext(
|
||||
classProto.typeParameterList,
|
||||
nameResolver,
|
||||
TypeTable(classProto.typeTable),
|
||||
classId.relativeClassName,
|
||||
containerSource,
|
||||
annotationDeserializer,
|
||||
status.isInner
|
||||
) ?: FirDeserializationContext.createForClass(
|
||||
classId, classProto, nameResolver, session,
|
||||
annotationDeserializer,
|
||||
FirConstDeserializer(session, (containerSource as? KotlinJvmBinarySourceElement)?.binaryClass),
|
||||
containerSource
|
||||
)
|
||||
if (status.isCompanion) {
|
||||
parentContext?.let {
|
||||
context.annotationDeserializer.inheritAnnotationInfo(it.annotationDeserializer)
|
||||
}
|
||||
}
|
||||
buildRegularClass {
|
||||
this.session = session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
name = classId.shortClassName
|
||||
this.status = status
|
||||
classKind = ProtoEnumFlags.classKind(kind)
|
||||
this.scopeProvider = scopeProvider
|
||||
this.symbol = symbol
|
||||
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
|
||||
typeParameters += context.typeDeserializer.ownTypeParameters.map { it.fir }
|
||||
if (status.isInner)
|
||||
typeParameters += parentContext?.allTypeParameters?.map { buildOuterClassTypeParameterRef { this.symbol = it } }.orEmpty()
|
||||
|
||||
val typeDeserializer = context.typeDeserializer
|
||||
val classDeserializer = context.memberDeserializer
|
||||
|
||||
val superTypesDeserialized = classProto.supertypes(context.typeTable).map { supertypeProto ->
|
||||
typeDeserializer.simpleType(supertypeProto, ConeAttributes.Empty)
|
||||
}// TODO: + c.components.additionalClassPartsProvider.getSupertypes(this@DeserializedClassDescriptor)
|
||||
|
||||
superTypesDeserialized.mapNotNullTo(superTypeRefs) {
|
||||
if (it == null) return@mapNotNullTo null
|
||||
buildResolvedTypeRef { type = it }
|
||||
}
|
||||
|
||||
addDeclarations(
|
||||
classProto.functionList.map {
|
||||
classDeserializer.loadFunction(it, classProto)
|
||||
}
|
||||
)
|
||||
|
||||
addDeclarations(
|
||||
classProto.propertyList.map {
|
||||
classDeserializer.loadProperty(it, classProto)
|
||||
}
|
||||
)
|
||||
|
||||
addDeclarations(
|
||||
classProto.constructorList.map {
|
||||
classDeserializer.loadConstructor(it, classProto, this)
|
||||
}
|
||||
)
|
||||
|
||||
addDeclarations(
|
||||
classProto.nestedClassNameList.mapNotNull { nestedNameId ->
|
||||
val nestedClassId = classId.createNestedClassId(Name.identifier(nameResolver.getString(nestedNameId)))
|
||||
deserializeNestedClass(nestedClassId, context)?.fir
|
||||
}
|
||||
)
|
||||
|
||||
addDeclarations(
|
||||
classProto.enumEntryList.mapNotNull { enumEntryProto ->
|
||||
val enumEntryName = nameResolver.getName(enumEntryProto.name)
|
||||
|
||||
val enumType = ConeClassLikeTypeImpl(symbol.toLookupTag(), emptyArray(), false)
|
||||
val property = buildEnumEntry {
|
||||
this.session = session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
returnTypeRef = buildResolvedTypeRef { type = enumType }
|
||||
name = enumEntryName
|
||||
this.symbol = FirVariableSymbol(CallableId(classId, enumEntryName))
|
||||
this.status = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Public,
|
||||
Modality.FINAL
|
||||
).apply {
|
||||
isStatic = true
|
||||
}
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
}
|
||||
|
||||
property
|
||||
}
|
||||
)
|
||||
|
||||
if (classKind == ClassKind.ENUM_CLASS) {
|
||||
generateValuesFunction(session, classId.packageFqName, classId.relativeClassName)
|
||||
generateValueOfFunction(session, classId.packageFqName, classId.relativeClassName)
|
||||
}
|
||||
|
||||
addCloneForArrayIfNeeded(classId)
|
||||
addSerializableIfNeeded(classId)
|
||||
}.also {
|
||||
if (isSealed) {
|
||||
it.sealedInheritors = classProto.sealedSubclassFqNameList.map { nameIndex ->
|
||||
ClassId.fromString(nameResolver.getQualifiedClassName(nameIndex))
|
||||
}
|
||||
}
|
||||
(it.annotations as MutableList<FirAnnotationCall>) +=
|
||||
context.annotationDeserializer.loadClassAnnotations(classProto, context.nameResolver)
|
||||
}
|
||||
}
|
||||
|
||||
private val ARRAY = Name.identifier("Array")
|
||||
private val ARRAY_CLASSES: Set<Name> = setOf(
|
||||
ARRAY,
|
||||
Name.identifier("ByteArray"),
|
||||
Name.identifier("CharArray"),
|
||||
Name.identifier("ShortArray"),
|
||||
Name.identifier("IntArray"),
|
||||
Name.identifier("LongArray"),
|
||||
Name.identifier("FloatArray"),
|
||||
Name.identifier("DoubleArray"),
|
||||
Name.identifier("BooleanArray"),
|
||||
)
|
||||
|
||||
private val JAVA_IO_SERIALIZABLE = ClassId.topLevel(FqName("java.io.Serializable"))
|
||||
|
||||
private fun FirRegularClassBuilder.addSerializableIfNeeded(classId: ClassId) {
|
||||
if (!JvmBuiltInsSettings.isSerializableInJava(classId.asSingleFqName().toUnsafe())) return
|
||||
superTypeRefs += buildResolvedTypeRef {
|
||||
type = ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(JAVA_IO_SERIALIZABLE),
|
||||
typeArguments = emptyArray(),
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirRegularClassBuilder.addCloneForArrayIfNeeded(classId: ClassId) {
|
||||
if (classId.packageFqName != StandardNames.BUILT_INS_PACKAGE_FQ_NAME) return
|
||||
if (classId.shortClassName !in ARRAY_CLASSES) return
|
||||
superTypeRefs += buildResolvedTypeRef {
|
||||
type = ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(CLONEABLE_CLASS_ID),
|
||||
typeArguments = emptyArray(),
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
declarations += buildSimpleFunction {
|
||||
session = this@addCloneForArrayIfNeeded.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
returnTypeRef = buildResolvedTypeRef {
|
||||
val typeArguments = if (classId.shortClassName == ARRAY) {
|
||||
arrayOf(
|
||||
ConeTypeParameterTypeImpl(
|
||||
ConeTypeParameterLookupTag(this@addCloneForArrayIfNeeded.typeParameters.first().symbol), isNullable = false
|
||||
)
|
||||
)
|
||||
} else {
|
||||
emptyArray()
|
||||
}
|
||||
type = ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(classId),
|
||||
typeArguments = typeArguments,
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
status = FirResolvedDeclarationStatusImpl(Visibilities.Public, Modality.FINAL).apply {
|
||||
isOverride = true
|
||||
}
|
||||
name = CLONE
|
||||
symbol = FirNamedFunctionSymbol(CallableId(classId, CLONE))
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
|
||||
class FirBuiltinAnnotationDeserializer(
|
||||
session: FirSession
|
||||
) : AbstractAnnotationDeserializer(session) {
|
||||
|
||||
override fun loadTypeAnnotations(typeProto: ProtoBuf.Type, nameResolver: NameResolver): List<FirAnnotationCall> {
|
||||
if (!Flags.HAS_ANNOTATIONS.get(typeProto.flags)) return emptyList()
|
||||
val annotations = typeProto.getExtension(protocol.typeAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
}
|
||||
+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)
|
||||
}
|
||||
}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* 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.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
|
||||
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
||||
import org.jetbrains.kotlin.fir.contracts.builder.buildEffectDeclaration
|
||||
import org.jetbrains.kotlin.fir.contracts.builder.buildResolvedContractDescription
|
||||
import org.jetbrains.kotlin.fir.contracts.description.*
|
||||
import org.jetbrains.kotlin.fir.contracts.toFirEffectDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirContractDescriptionOwner
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.LogicOperationKind
|
||||
import org.jetbrains.kotlin.fir.types.ConeAttributes
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.isBoolean
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.metadata.deserialization.isInstanceType
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
class FirContractDeserializer(private val c: FirDeserializationContext) {
|
||||
fun loadContract(proto: ProtoBuf.Contract, owner: FirContractDescriptionOwner): FirContractDescription? {
|
||||
val effects = proto.effectList.map { loadPossiblyConditionalEffect(it, owner) ?: return null }
|
||||
return buildResolvedContractDescription {
|
||||
this.effects += effects.map { it.toFirEffectDeclaration() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadPossiblyConditionalEffect(
|
||||
proto: ProtoBuf.Effect,
|
||||
owner: FirContractDescriptionOwner
|
||||
): ConeEffectDeclaration? {
|
||||
if (proto.hasConclusionOfConditionalEffect()) {
|
||||
val conclusion = loadExpression(proto.conclusionOfConditionalEffect, owner) ?: return null
|
||||
val effect = loadSimpleEffect(proto, owner) ?: return null
|
||||
return ConeConditionalEffectDeclaration(effect, conclusion)
|
||||
}
|
||||
return loadSimpleEffect(proto, owner)
|
||||
}
|
||||
|
||||
private fun loadSimpleEffect(proto: ProtoBuf.Effect, owner: FirContractDescriptionOwner): ConeEffectDeclaration? {
|
||||
val type: ProtoBuf.Effect.EffectType = if (proto.hasEffectType()) proto.effectType else return null
|
||||
return when(type) {
|
||||
ProtoBuf.Effect.EffectType.RETURNS_CONSTANT -> {
|
||||
val argument = proto.effectConstructorArgumentList.firstOrNull()
|
||||
val returnValue = if (argument == null) {
|
||||
ConeConstantReference.WILDCARD
|
||||
} else {
|
||||
loadExpression(argument, owner) as? ConeConstantReference ?: return null
|
||||
}
|
||||
ConeReturnsEffectDeclaration(returnValue)
|
||||
}
|
||||
ProtoBuf.Effect.EffectType.RETURNS_NOT_NULL -> {
|
||||
ConeReturnsEffectDeclaration(ConeConstantReference.NOT_NULL)
|
||||
}
|
||||
ProtoBuf.Effect.EffectType.CALLS -> {
|
||||
val argument = proto.effectConstructorArgumentList.firstOrNull() ?: return null
|
||||
val callable = extractVariable(argument, owner) ?: return null
|
||||
val invocationKind = if (proto.hasKind())
|
||||
proto.kind.toDescriptorInvocationKind() ?: return null
|
||||
else
|
||||
EventOccurrencesRange.UNKNOWN
|
||||
ConeCallsEffectDeclaration(callable, invocationKind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadExpression(proto: ProtoBuf.Expression, owner: FirContractDescriptionOwner): ConeBooleanExpression? {
|
||||
val primitiveType = getPrimitiveType(proto)
|
||||
val primitiveExpression = extractPrimitiveExpression(proto, primitiveType, owner)
|
||||
|
||||
val complexType = getComplexType(proto)
|
||||
val childs: MutableList<ConeBooleanExpression> = mutableListOf()
|
||||
childs.addIfNotNull(primitiveExpression)
|
||||
|
||||
return when (complexType) {
|
||||
ComplexExpressionType.AND_SEQUENCE -> {
|
||||
proto.andArgumentList.mapTo(childs) { loadExpression(it, owner) ?: return null }
|
||||
childs.reduce { acc, booleanExpression -> ConeBinaryLogicExpression(acc, booleanExpression, LogicOperationKind.AND) }
|
||||
}
|
||||
|
||||
ComplexExpressionType.OR_SEQUENCE -> {
|
||||
proto.orArgumentList.mapTo(childs) { loadExpression(it, owner) ?: return null }
|
||||
childs.reduce { acc, booleanExpression -> ConeBinaryLogicExpression(acc, booleanExpression, LogicOperationKind.OR) }
|
||||
}
|
||||
|
||||
null -> primitiveExpression
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractPrimitiveExpression(proto: ProtoBuf.Expression, primitiveType: PrimitiveExpressionType?, owner: FirContractDescriptionOwner): ConeBooleanExpression? {
|
||||
val isInverted = Flags.IS_NEGATED.get(proto.flags)
|
||||
|
||||
return when (primitiveType) {
|
||||
PrimitiveExpressionType.VALUE_PARAMETER_REFERENCE, PrimitiveExpressionType.RECEIVER_REFERENCE -> {
|
||||
(extractVariable(proto, owner) as? ConeBooleanValueParameterReference?)?.invertIfNecessary(isInverted)
|
||||
}
|
||||
|
||||
PrimitiveExpressionType.CONSTANT ->
|
||||
(loadConstant(proto.constantValue) as? ConeBooleanConstantReference)?.invertIfNecessary(isInverted)
|
||||
|
||||
PrimitiveExpressionType.INSTANCE_CHECK -> {
|
||||
val variable = extractVariable(proto, owner) ?: return null
|
||||
val type = extractType(proto) ?: return null
|
||||
ConeIsInstancePredicate(variable, type, isInverted)
|
||||
}
|
||||
|
||||
PrimitiveExpressionType.NULLABILITY_CHECK -> {
|
||||
val variable = extractVariable(proto, owner) ?: return null
|
||||
ConeIsNullPredicate(variable, isInverted)
|
||||
}
|
||||
|
||||
null -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeBooleanExpression.invertIfNecessary(shouldInvert: Boolean): ConeBooleanExpression =
|
||||
if (shouldInvert) ConeLogicalNot(this) else this
|
||||
|
||||
private fun extractVariable(proto: ProtoBuf.Expression, owner: FirContractDescriptionOwner): ConeValueParameterReference? {
|
||||
if (!proto.hasValueParameterReference()) return null
|
||||
|
||||
val ownerFunction = owner as FirSimpleFunction
|
||||
|
||||
val valueParameterIndex = proto.valueParameterReference - 1
|
||||
|
||||
val name: String
|
||||
val typeRef = if (valueParameterIndex < 0) {
|
||||
name = "this"
|
||||
ownerFunction.receiverTypeRef
|
||||
} else {
|
||||
val parameter = ownerFunction.valueParameters.getOrNull(valueParameterIndex) ?: return null
|
||||
name = parameter.name.asString()
|
||||
parameter.returnTypeRef
|
||||
} ?: return null
|
||||
|
||||
return if (!typeRef.isBoolean)
|
||||
ConeValueParameterReference(valueParameterIndex, name)
|
||||
else
|
||||
ConeBooleanValueParameterReference(valueParameterIndex, name)
|
||||
}
|
||||
|
||||
private fun ProtoBuf.Effect.InvocationKind.toDescriptorInvocationKind(): EventOccurrencesRange? = when (this) {
|
||||
ProtoBuf.Effect.InvocationKind.AT_MOST_ONCE -> EventOccurrencesRange.AT_MOST_ONCE
|
||||
ProtoBuf.Effect.InvocationKind.EXACTLY_ONCE -> EventOccurrencesRange.EXACTLY_ONCE
|
||||
ProtoBuf.Effect.InvocationKind.AT_LEAST_ONCE -> EventOccurrencesRange.AT_LEAST_ONCE
|
||||
}
|
||||
|
||||
private fun extractType(proto: ProtoBuf.Expression): ConeKotlinType? {
|
||||
return c.typeDeserializer.type(proto.isInstanceType(c.typeTable) ?: return null, ConeAttributes.Empty)
|
||||
}
|
||||
|
||||
private fun loadConstant(value: ProtoBuf.Expression.ConstantValue): ConeConstantReference? = when (value) {
|
||||
ProtoBuf.Expression.ConstantValue.TRUE -> ConeBooleanConstantReference.TRUE
|
||||
ProtoBuf.Expression.ConstantValue.FALSE -> ConeBooleanConstantReference.FALSE
|
||||
ProtoBuf.Expression.ConstantValue.NULL -> ConeConstantReference.NULL
|
||||
}
|
||||
|
||||
|
||||
private fun getComplexType(proto: ProtoBuf.Expression): ComplexExpressionType? {
|
||||
val isOrSequence = proto.orArgumentCount != 0
|
||||
val isAndSequence = proto.andArgumentCount != 0
|
||||
return when {
|
||||
isOrSequence && isAndSequence -> null
|
||||
isOrSequence -> ComplexExpressionType.OR_SEQUENCE
|
||||
isAndSequence -> ComplexExpressionType.AND_SEQUENCE
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPrimitiveType(proto: ProtoBuf.Expression): PrimitiveExpressionType? {
|
||||
// Expected to be one element, but can be empty (unknown expression) or contain several elements (invalid data)
|
||||
val expressionTypes: MutableList<PrimitiveExpressionType> = mutableListOf()
|
||||
|
||||
// Check for predicates
|
||||
when {
|
||||
proto.hasValueParameterReference() && proto.hasType() ->
|
||||
expressionTypes.add(PrimitiveExpressionType.INSTANCE_CHECK)
|
||||
|
||||
proto.hasValueParameterReference() && Flags.IS_NULL_CHECK_PREDICATE.get(proto.flags) ->
|
||||
expressionTypes.add(PrimitiveExpressionType.NULLABILITY_CHECK)
|
||||
}
|
||||
|
||||
// If message contains correct predicate, then predicate's type overrides type of value,
|
||||
// even is message has one
|
||||
if (expressionTypes.isNotEmpty()) {
|
||||
return expressionTypes.singleOrNull()
|
||||
}
|
||||
|
||||
// Otherwise, check if it is a value
|
||||
when {
|
||||
proto.hasValueParameterReference() && proto.valueParameterReference > 0 ->
|
||||
expressionTypes.add(PrimitiveExpressionType.VALUE_PARAMETER_REFERENCE)
|
||||
|
||||
proto.hasValueParameterReference() && proto.valueParameterReference == 0 ->
|
||||
expressionTypes.add(PrimitiveExpressionType.RECEIVER_REFERENCE)
|
||||
|
||||
proto.hasConstantValue() -> expressionTypes.add(PrimitiveExpressionType.CONSTANT)
|
||||
}
|
||||
|
||||
return expressionTypes.singleOrNull()
|
||||
}
|
||||
|
||||
private fun ProtoBuf.Expression.hasType(): Boolean = this.hasIsInstanceType() || this.hasIsInstanceTypeId()
|
||||
|
||||
// Arguments of expressions with such types are never other expressions
|
||||
private enum class PrimitiveExpressionType {
|
||||
VALUE_PARAMETER_REFERENCE,
|
||||
RECEIVER_REFERENCE,
|
||||
CONSTANT,
|
||||
INSTANCE_CHECK,
|
||||
NULLABILITY_CHECK
|
||||
}
|
||||
|
||||
// Expressions with such type can take other expressions as arguments.
|
||||
// Additionally, for performance reasons, "complex expression" and "primitive expression"
|
||||
// can co-exist in the one and the same message. If "primitive expression" is present
|
||||
// in the current message, it is treated as the first argument of "complex expression".
|
||||
private enum class ComplexExpressionType {
|
||||
AND_SEQUENCE,
|
||||
OR_SEQUENCE
|
||||
|
||||
}
|
||||
}
|
||||
+491
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* 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.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeAttributes
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.computeTypeAttributes
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
|
||||
class FirDeserializationContext(
|
||||
val nameResolver: NameResolver,
|
||||
val typeTable: TypeTable,
|
||||
val versionRequirementTable: VersionRequirementTable,
|
||||
val session: FirSession,
|
||||
val packageFqName: FqName,
|
||||
val relativeClassName: FqName?,
|
||||
val typeDeserializer: FirTypeDeserializer,
|
||||
val annotationDeserializer: AbstractAnnotationDeserializer,
|
||||
val constDeserializer: FirConstDeserializer,
|
||||
val containerSource: DeserializedContainerSource?,
|
||||
outerTypeParameters: List<FirTypeParameterSymbol>,
|
||||
val components: FirDeserializationComponents
|
||||
) {
|
||||
val allTypeParameters: List<FirTypeParameterSymbol> =
|
||||
typeDeserializer.ownTypeParameters + outerTypeParameters
|
||||
|
||||
fun childContext(
|
||||
typeParameterProtos: List<ProtoBuf.TypeParameter>,
|
||||
nameResolver: NameResolver = this.nameResolver,
|
||||
typeTable: TypeTable = this.typeTable,
|
||||
relativeClassName: FqName? = this.relativeClassName,
|
||||
containerSource: DeserializedContainerSource? = this.containerSource,
|
||||
annotationDeserializer: AbstractAnnotationDeserializer = this.annotationDeserializer,
|
||||
capturesTypeParameters: Boolean = true
|
||||
): FirDeserializationContext = FirDeserializationContext(
|
||||
nameResolver, typeTable, versionRequirementTable, session, packageFqName, relativeClassName,
|
||||
FirTypeDeserializer(
|
||||
session, nameResolver, typeTable, typeParameterProtos, typeDeserializer
|
||||
),
|
||||
annotationDeserializer, constDeserializer, containerSource,
|
||||
if (capturesTypeParameters) allTypeParameters else emptyList(), components
|
||||
)
|
||||
|
||||
val memberDeserializer: FirMemberDeserializer = FirMemberDeserializer(this)
|
||||
|
||||
companion object {
|
||||
fun createForPackage(
|
||||
fqName: FqName,
|
||||
packageProto: ProtoBuf.Package,
|
||||
nameResolver: NameResolver,
|
||||
session: FirSession,
|
||||
annotationDeserializer: AbstractAnnotationDeserializer,
|
||||
constDeserializer: FirConstDeserializer,
|
||||
containerSource: DeserializedContainerSource?
|
||||
) = createRootContext(
|
||||
nameResolver,
|
||||
TypeTable(packageProto.typeTable),
|
||||
session,
|
||||
annotationDeserializer,
|
||||
constDeserializer,
|
||||
fqName,
|
||||
relativeClassName = null,
|
||||
typeParameterProtos = emptyList(),
|
||||
containerSource
|
||||
)
|
||||
|
||||
fun createForClass(
|
||||
classId: ClassId,
|
||||
classProto: ProtoBuf.Class,
|
||||
nameResolver: NameResolver,
|
||||
session: FirSession,
|
||||
annotationDeserializer: AbstractAnnotationDeserializer,
|
||||
constDeserializer: FirConstDeserializer,
|
||||
containerSource: DeserializedContainerSource?
|
||||
) = createRootContext(
|
||||
nameResolver,
|
||||
TypeTable(classProto.typeTable),
|
||||
session,
|
||||
annotationDeserializer,
|
||||
constDeserializer,
|
||||
classId.packageFqName,
|
||||
classId.relativeClassName,
|
||||
classProto.typeParameterList,
|
||||
containerSource
|
||||
)
|
||||
|
||||
private fun createRootContext(
|
||||
nameResolver: NameResolver,
|
||||
typeTable: TypeTable,
|
||||
session: FirSession,
|
||||
annotationDeserializer: AbstractAnnotationDeserializer,
|
||||
constDeserializer: FirConstDeserializer,
|
||||
packageFqName: FqName,
|
||||
relativeClassName: FqName?,
|
||||
typeParameterProtos: List<ProtoBuf.TypeParameter>,
|
||||
containerSource: DeserializedContainerSource?
|
||||
): FirDeserializationContext {
|
||||
return FirDeserializationContext(
|
||||
nameResolver, typeTable,
|
||||
VersionRequirementTable.EMPTY, // TODO:
|
||||
session,
|
||||
packageFqName,
|
||||
relativeClassName,
|
||||
FirTypeDeserializer(
|
||||
session,
|
||||
nameResolver,
|
||||
typeTable,
|
||||
typeParameterProtos,
|
||||
null
|
||||
),
|
||||
annotationDeserializer,
|
||||
constDeserializer,
|
||||
containerSource,
|
||||
emptyList(),
|
||||
FirDeserializationComponents()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move something here
|
||||
class FirDeserializationComponents {
|
||||
|
||||
}
|
||||
|
||||
class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
||||
private val contractDeserializer = FirContractDeserializer(c)
|
||||
|
||||
private fun loadOldFlags(oldFlags: Int): Int {
|
||||
val lowSixBits = oldFlags and 0x3f
|
||||
val rest = (oldFlags shr 8) shl 6
|
||||
return lowSixBits + rest
|
||||
}
|
||||
|
||||
fun loadTypeAlias(proto: ProtoBuf.TypeAlias): FirTypeAlias {
|
||||
val flags = proto.flags
|
||||
val name = c.nameResolver.getName(proto.name)
|
||||
val local = c.childContext(proto.typeParameterList)
|
||||
val classId = ClassId(c.packageFqName, name)
|
||||
return buildTypeAlias {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
this.name = name
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
FirProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)),
|
||||
Modality.FINAL
|
||||
).apply {
|
||||
isExpect = Flags.IS_EXPECT_CLASS.get(flags)
|
||||
isActual = false
|
||||
}
|
||||
symbol = FirTypeAliasSymbol(classId)
|
||||
expandedTypeRef = buildResolvedTypeRef {
|
||||
type = local.typeDeserializer.type(proto.underlyingType(c.typeTable), ConeAttributes.Empty)
|
||||
}
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
|
||||
}
|
||||
}
|
||||
|
||||
fun loadProperty(
|
||||
proto: ProtoBuf.Property,
|
||||
classProto: ProtoBuf.Class? = null
|
||||
): FirProperty {
|
||||
val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags)
|
||||
val callableName = c.nameResolver.getName(proto.name)
|
||||
val callableId = CallableId(c.packageFqName, c.relativeClassName, callableName)
|
||||
val symbol = FirPropertySymbol(callableId)
|
||||
val local = c.childContext(proto.typeParameterList)
|
||||
|
||||
// Per documentation on Property.getter_flags in metadata.proto, if an accessor flags field is absent, its value should be computed
|
||||
// by taking hasAnnotations/visibility/modality from property flags, and using false for the rest
|
||||
val defaultAccessorFlags = Flags.getAccessorFlags(
|
||||
Flags.HAS_ANNOTATIONS.get(flags),
|
||||
Flags.VISIBILITY.get(flags),
|
||||
Flags.MODALITY.get(flags),
|
||||
false, false, false
|
||||
)
|
||||
|
||||
val returnTypeRef = proto.returnType(c.typeTable).toTypeRef(local)
|
||||
|
||||
val hasGetter = Flags.HAS_GETTER.get(flags)
|
||||
val receiverAnnotations = if (hasGetter && proto.hasReceiver()) {
|
||||
c.annotationDeserializer.loadExtensionReceiverParameterAnnotations(
|
||||
c.containerSource, proto, local.nameResolver, local.typeTable, AbstractAnnotationDeserializer.CallableKind.PROPERTY_GETTER
|
||||
)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
val getter = if (hasGetter) {
|
||||
val getterFlags = if (proto.hasGetterFlags()) proto.getterFlags else defaultAccessorFlags
|
||||
val visibility = FirProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags))
|
||||
val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(getterFlags))
|
||||
if (Flags.IS_NOT_DEFAULT.get(getterFlags)) {
|
||||
buildPropertyAccessor {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
this.returnTypeRef = returnTypeRef
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
isGetter = true
|
||||
status = FirResolvedDeclarationStatusImpl(visibility, modality)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadPropertyGetterAnnotations(
|
||||
c.containerSource, proto, local.nameResolver, local.typeTable, getterFlags
|
||||
)
|
||||
this.symbol = FirPropertyAccessorSymbol()
|
||||
}
|
||||
} else {
|
||||
FirDefaultPropertyGetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val setter = if (Flags.HAS_SETTER.get(flags)) {
|
||||
val setterFlags = if (proto.hasSetterFlags()) proto.setterFlags else defaultAccessorFlags
|
||||
val visibility = FirProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags))
|
||||
val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(setterFlags))
|
||||
if (Flags.IS_NOT_DEFAULT.get(setterFlags)) {
|
||||
buildPropertyAccessor {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
this.returnTypeRef = FirImplicitUnitTypeRef(source)
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
isGetter = false
|
||||
status = FirResolvedDeclarationStatusImpl(visibility, modality)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadPropertySetterAnnotations(
|
||||
c.containerSource, proto, local.nameResolver, local.typeTable, setterFlags
|
||||
)
|
||||
this.symbol = FirPropertyAccessorSymbol()
|
||||
valueParameters += local.memberDeserializer.valueParameters(
|
||||
listOf(proto.setterValueParameter),
|
||||
proto,
|
||||
AbstractAnnotationDeserializer.CallableKind.PROPERTY_SETTER,
|
||||
classProto
|
||||
)
|
||||
}
|
||||
} else {
|
||||
FirDefaultPropertySetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val isVar = Flags.IS_VAR.get(flags)
|
||||
return buildProperty {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
this.returnTypeRef = returnTypeRef
|
||||
receiverTypeRef = proto.receiverType(c.typeTable)?.toTypeRef(local).apply {
|
||||
annotations += receiverAnnotations
|
||||
}
|
||||
name = callableName
|
||||
this.isVar = isVar
|
||||
this.symbol = symbol
|
||||
isLocal = false
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
FirProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)),
|
||||
ProtoEnumFlags.modality(Flags.MODALITY.get(flags))
|
||||
).apply {
|
||||
isExpect = Flags.IS_EXPECT_PROPERTY.get(flags)
|
||||
isActual = false
|
||||
isOverride = false
|
||||
isConst = Flags.IS_CONST.get(flags)
|
||||
isLateInit = Flags.IS_LATEINIT.get(flags)
|
||||
}
|
||||
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadPropertyAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadPropertyBackingFieldAnnotations(
|
||||
c.containerSource, proto, local.nameResolver, local.typeTable
|
||||
)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadPropertyDelegatedFieldAnnotations(
|
||||
c.containerSource, proto, local.nameResolver, local.typeTable
|
||||
)
|
||||
this.getter = getter
|
||||
this.setter = setter
|
||||
this.containerSource = c.containerSource
|
||||
this.initializer = c.constDeserializer.loadConstant(proto, symbol.callableId, c.nameResolver)
|
||||
}
|
||||
}
|
||||
|
||||
fun loadFunction(
|
||||
proto: ProtoBuf.Function,
|
||||
classProto: ProtoBuf.Class? = null
|
||||
): FirSimpleFunction {
|
||||
val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags)
|
||||
|
||||
val receiverAnnotations = if (proto.hasReceiver()) {
|
||||
c.annotationDeserializer.loadExtensionReceiverParameterAnnotations(
|
||||
c.containerSource, proto, c.nameResolver, c.typeTable, AbstractAnnotationDeserializer.CallableKind.OTHERS
|
||||
)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
val versionRequirementTable =
|
||||
// TODO: Support case for KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME
|
||||
c.versionRequirementTable
|
||||
|
||||
val callableName = c.nameResolver.getName(proto.name)
|
||||
val callableId = CallableId(c.packageFqName, c.relativeClassName, callableName)
|
||||
val symbol = FirNamedFunctionSymbol(callableId)
|
||||
val local = c.childContext(proto.typeParameterList)
|
||||
// TODO: support contracts
|
||||
|
||||
val simpleFunction = buildSimpleFunction {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
returnTypeRef = proto.returnType(local.typeTable).toTypeRef(local)
|
||||
receiverTypeRef = proto.receiverType(local.typeTable)?.toTypeRef(local).apply {
|
||||
annotations += receiverAnnotations
|
||||
}
|
||||
name = callableName
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
FirProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags)),
|
||||
ProtoEnumFlags.modality(Flags.MODALITY.get(flags))
|
||||
).apply {
|
||||
isExpect = Flags.IS_EXPECT_FUNCTION.get(flags)
|
||||
isActual = false
|
||||
isOverride = false
|
||||
isOperator = Flags.IS_OPERATOR.get(flags)
|
||||
isInfix = Flags.IS_INFIX.get(flags)
|
||||
isInline = Flags.IS_INLINE.get(flags)
|
||||
isTailRec = Flags.IS_TAILREC.get(flags)
|
||||
isExternal = Flags.IS_EXTERNAL_FUNCTION.get(flags)
|
||||
isSuspend = Flags.IS_SUSPEND.get(flags)
|
||||
}
|
||||
this.symbol = symbol
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
|
||||
valueParameters += local.memberDeserializer.valueParameters(
|
||||
proto.valueParameterList,
|
||||
proto,
|
||||
AbstractAnnotationDeserializer.CallableKind.OTHERS,
|
||||
classProto
|
||||
)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadFunctionAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
|
||||
this.containerSource = c.containerSource
|
||||
}
|
||||
if (proto.hasContract()) {
|
||||
val contractDescription = contractDeserializer.loadContract(proto.contract, simpleFunction)
|
||||
if (contractDescription != null) {
|
||||
simpleFunction.replaceContractDescription(contractDescription)
|
||||
}
|
||||
}
|
||||
return simpleFunction
|
||||
}
|
||||
|
||||
fun loadConstructor(
|
||||
proto: ProtoBuf.Constructor,
|
||||
classProto: ProtoBuf.Class,
|
||||
classBuilder: FirRegularClassBuilder
|
||||
): FirConstructor {
|
||||
val flags = proto.flags
|
||||
val relativeClassName = c.relativeClassName!!
|
||||
val callableId = CallableId(c.packageFqName, relativeClassName, relativeClassName.shortName())
|
||||
val symbol = FirConstructorSymbol(callableId)
|
||||
val local = c.childContext(emptyList())
|
||||
val isPrimary = !Flags.IS_SECONDARY.get(flags)
|
||||
|
||||
val typeParameters = classBuilder.typeParameters
|
||||
|
||||
val delegatedSelfType = buildResolvedTypeRef {
|
||||
type = ConeClassLikeTypeImpl(
|
||||
classBuilder.symbol.toLookupTag(),
|
||||
typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
return if (isPrimary) {
|
||||
FirPrimaryConstructorBuilder()
|
||||
} else {
|
||||
FirConstructorBuilder()
|
||||
}.apply {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
returnTypeRef = delegatedSelfType
|
||||
val visibility = FirProtoEnumFlags.visibility(Flags.VISIBILITY.get(flags))
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
visibility,
|
||||
Modality.FINAL
|
||||
).apply {
|
||||
isExpect = Flags.IS_EXPECT_FUNCTION.get(flags)
|
||||
isActual = false
|
||||
isOverride = false
|
||||
isInner = classBuilder.status.isInner
|
||||
}
|
||||
this.symbol = symbol
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
this.typeParameters +=
|
||||
typeParameters.filterIsInstance<FirTypeParameter>()
|
||||
.map { buildConstructedClassTypeParameterRef { this.symbol = it.symbol } }
|
||||
valueParameters += local.memberDeserializer.valueParameters(
|
||||
proto.valueParameterList,
|
||||
proto,
|
||||
AbstractAnnotationDeserializer.CallableKind.OTHERS,
|
||||
classProto,
|
||||
addDefaultValue = classBuilder.symbol.classId == StandardClassIds.Enum
|
||||
)
|
||||
annotations +=
|
||||
c.annotationDeserializer.loadConstructorAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
|
||||
}.build()
|
||||
}
|
||||
|
||||
private fun defaultValue(flags: Int): FirExpression? {
|
||||
if (Flags.DECLARES_DEFAULT_VALUE.get(flags)) {
|
||||
return buildExpressionStub()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun valueParameters(
|
||||
valueParameters: List<ProtoBuf.ValueParameter>,
|
||||
callableProto: MessageLite,
|
||||
callableKind: AbstractAnnotationDeserializer.CallableKind,
|
||||
classProto: ProtoBuf.Class?,
|
||||
addDefaultValue: Boolean = false
|
||||
): List<FirValueParameter> {
|
||||
return valueParameters.mapIndexed { index, proto ->
|
||||
val flags = if (proto.hasFlags()) proto.flags else 0
|
||||
val name = c.nameResolver.getName(proto.name)
|
||||
buildValueParameter {
|
||||
session = c.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
returnTypeRef = proto.type(c.typeTable).toTypeRef(c)
|
||||
this.name = name
|
||||
symbol = FirVariableSymbol(name)
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
defaultValue = defaultValue(flags)
|
||||
if (addDefaultValue) {
|
||||
defaultValue = buildExpressionStub()
|
||||
}
|
||||
isCrossinline = Flags.IS_CROSSINLINE.get(flags)
|
||||
isNoinline = Flags.IS_NOINLINE.get(flags)
|
||||
isVararg = proto.varargElementType(c.typeTable) != null
|
||||
annotations += c.annotationDeserializer.loadValueParameterAnnotations(
|
||||
c.containerSource,
|
||||
callableProto,
|
||||
proto,
|
||||
classProto,
|
||||
c.nameResolver,
|
||||
c.typeTable,
|
||||
callableKind,
|
||||
index,
|
||||
)
|
||||
}
|
||||
}.toList()
|
||||
}
|
||||
|
||||
private fun ProtoBuf.Type.toTypeRef(context: FirDeserializationContext): FirTypeRef {
|
||||
return buildResolvedTypeRef {
|
||||
annotations += context.annotationDeserializer.loadTypeAnnotations(this@toTypeRef, context.nameResolver)
|
||||
val attributes = annotations.computeTypeAttributes()
|
||||
type = context.typeDeserializer.type(this@toTypeRef, attributes)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.Visibilities
|
||||
import org.jetbrains.kotlin.fir.Visibility
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
|
||||
object FirProtoEnumFlags {
|
||||
fun visibility(visibility: ProtoBuf.Visibility?): Visibility = when (visibility) {
|
||||
ProtoBuf.Visibility.INTERNAL -> Visibilities.Internal
|
||||
ProtoBuf.Visibility.PRIVATE -> Visibilities.Private
|
||||
ProtoBuf.Visibility.PRIVATE_TO_THIS -> Visibilities.PrivateToThis
|
||||
ProtoBuf.Visibility.PROTECTED -> Visibilities.Protected
|
||||
ProtoBuf.Visibility.PUBLIC -> Visibilities.Public
|
||||
ProtoBuf.Visibility.LOCAL -> Visibilities.Local
|
||||
else -> Visibilities.Private
|
||||
}
|
||||
|
||||
fun visibility(visibility: Visibility): ProtoBuf.Visibility = when (visibility) {
|
||||
Visibilities.Internal -> ProtoBuf.Visibility.INTERNAL
|
||||
Visibilities.Public -> ProtoBuf.Visibility.PUBLIC
|
||||
Visibilities.Private -> ProtoBuf.Visibility.PRIVATE
|
||||
Visibilities.PrivateToThis -> ProtoBuf.Visibility.PRIVATE_TO_THIS
|
||||
Visibilities.Protected -> ProtoBuf.Visibility.PROTECTED
|
||||
Visibilities.Local -> ProtoBuf.Visibility.LOCAL
|
||||
else -> throw IllegalArgumentException("Unknown visibility: $visibility")
|
||||
}
|
||||
}
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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.builtins.functions.FunctionClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRefsOwner
|
||||
import org.jetbrains.kotlin.fir.declarations.addDefaultBoundIfNecessary
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.FirTypeParameterBuilder
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
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.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import java.util.*
|
||||
|
||||
class FirTypeDeserializer(
|
||||
val session: FirSession,
|
||||
val nameResolver: NameResolver,
|
||||
val typeTable: TypeTable,
|
||||
typeParameterProtos: List<ProtoBuf.TypeParameter>,
|
||||
val parent: FirTypeDeserializer?
|
||||
) {
|
||||
private val typeParameterDescriptors: Map<Int, FirTypeParameterSymbol> = if (typeParameterProtos.isNotEmpty()) {
|
||||
LinkedHashMap<Int, FirTypeParameterSymbol>()
|
||||
} else {
|
||||
mapOf()
|
||||
}
|
||||
|
||||
private val typeParameterNames: Map<String, FirTypeParameterSymbol>
|
||||
|
||||
val ownTypeParameters: List<FirTypeParameterSymbol>
|
||||
get() = typeParameterDescriptors.values.toList()
|
||||
|
||||
init {
|
||||
if (typeParameterProtos.isNotEmpty()) {
|
||||
typeParameterNames = mutableMapOf()
|
||||
val result = typeParameterDescriptors as LinkedHashMap<Int, FirTypeParameterSymbol>
|
||||
val builders = mutableListOf<FirTypeParameterBuilder>()
|
||||
for (proto in typeParameterProtos) {
|
||||
if (!proto.hasId()) continue
|
||||
val name = nameResolver.getName(proto.name)
|
||||
val symbol = FirTypeParameterSymbol().also {
|
||||
typeParameterNames[name.asString()] = it
|
||||
}
|
||||
builders += FirTypeParameterBuilder().apply {
|
||||
session = this@FirTypeDeserializer.session
|
||||
origin = FirDeclarationOrigin.Library
|
||||
this.name = name
|
||||
this.symbol = symbol
|
||||
variance = proto.variance.convertVariance()
|
||||
isReified = proto.reified
|
||||
}
|
||||
result[proto.id] = symbol
|
||||
}
|
||||
|
||||
for ((index, proto) in typeParameterProtos.withIndex()) {
|
||||
val builder = builders[index]
|
||||
builder.apply {
|
||||
proto.upperBoundList.mapTo(bounds) {
|
||||
buildResolvedTypeRef { type = type(it, ConeAttributes.Empty) }
|
||||
}
|
||||
addDefaultBoundIfNecessary()
|
||||
}.build()
|
||||
}
|
||||
} else {
|
||||
typeParameterNames = emptyMap()
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeClassifier(fqNameIndex: Int): ConeClassLikeLookupTag? {
|
||||
try {
|
||||
val id = nameResolver.getClassId(fqNameIndex)
|
||||
return ConeClassLikeLookupTagImpl(id)
|
||||
} catch (e: Throwable) {
|
||||
throw RuntimeException("Looking up for ${nameResolver.getClassId(fqNameIndex)}", e)
|
||||
}
|
||||
}
|
||||
|
||||
fun type(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeKotlinType {
|
||||
if (proto.hasFlexibleTypeCapabilitiesId()) {
|
||||
val lowerBound = simpleType(proto, attributes)
|
||||
val upperBound = simpleType(proto.flexibleUpperBound(typeTable)!!, attributes)
|
||||
return ConeFlexibleType(lowerBound!!, upperBound!!)
|
||||
//c.components.flexibleTypeDeserializer.create(proto, id, lowerBound, upperBound)
|
||||
}
|
||||
|
||||
return simpleType(proto, attributes) ?: ConeKotlinErrorType(ConeSimpleDiagnostic("?!id:0", DiagnosticKind.DeserializationError))
|
||||
}
|
||||
|
||||
private fun typeParameterSymbol(typeParameterId: Int): ConeTypeParameterLookupTag? =
|
||||
typeParameterDescriptors[typeParameterId]?.toLookupTag() ?: parent?.typeParameterSymbol(typeParameterId)
|
||||
|
||||
|
||||
private fun ProtoBuf.TypeParameter.Variance.convertVariance(): Variance {
|
||||
return when (this) {
|
||||
ProtoBuf.TypeParameter.Variance.IN -> Variance.IN_VARIANCE
|
||||
ProtoBuf.TypeParameter.Variance.OUT -> Variance.OUT_VARIANCE
|
||||
ProtoBuf.TypeParameter.Variance.INV -> Variance.INVARIANT
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun FirClassLikeSymbol<*>.typeParameters(): List<FirTypeParameterSymbol> =
|
||||
(fir as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol }.orEmpty()
|
||||
|
||||
fun simpleType(proto: ProtoBuf.Type, attributes: ConeAttributes): ConeLookupTagBasedType? {
|
||||
|
||||
val constructor = typeSymbol(proto) ?: return null
|
||||
if (constructor is ConeTypeParameterLookupTag) return ConeTypeParameterTypeImpl(constructor, isNullable = proto.nullable)
|
||||
if (constructor !is ConeClassLikeLookupTag) return null
|
||||
|
||||
fun ProtoBuf.Type.collectAllArguments(): List<ProtoBuf.Type.Argument> =
|
||||
argumentList + outerType(typeTable)?.collectAllArguments().orEmpty()
|
||||
|
||||
val arguments = proto.collectAllArguments().map(this::typeArgument).toTypedArray()
|
||||
|
||||
val simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) {
|
||||
createSuspendFunctionType(constructor, arguments, isNullable = proto.nullable, attributes)
|
||||
} else {
|
||||
ConeClassLikeTypeImpl(constructor, arguments, isNullable = proto.nullable, attributes)
|
||||
}
|
||||
|
||||
val abbreviatedTypeProto = proto.abbreviatedType(typeTable) ?: return simpleType
|
||||
|
||||
return simpleType(abbreviatedTypeProto, attributes)
|
||||
|
||||
}
|
||||
|
||||
private fun createSuspendFunctionTypeForBasicCase(
|
||||
//annotations: Annotations, TODO?,
|
||||
functionTypeConstructor: ConeClassLikeLookupTag,
|
||||
arguments: Array<ConeTypeProjection>,
|
||||
isNullable: Boolean,
|
||||
attributes: ConeAttributes
|
||||
): ConeClassLikeType? {
|
||||
fun ConeClassLikeType.isContinuation(): Boolean {
|
||||
if (this.typeArguments.size != 1) return false
|
||||
if (this.lookupTag.classId != CONTINUATION_INTERFACE_CLASS_ID) return false
|
||||
return true
|
||||
}
|
||||
|
||||
val returnType = arguments.lastOrNull()
|
||||
val continuationType = arguments.getOrNull(arguments.lastIndex - 1) as? ConeClassLikeType ?: return null
|
||||
|
||||
if (!continuationType.isContinuation()) return ConeClassLikeTypeImpl(functionTypeConstructor, arguments, isNullable, attributes)
|
||||
|
||||
val suspendReturnType = continuationType.typeArguments.single() as ConeKotlinTypeProjection
|
||||
|
||||
val valueParameters = arguments.dropLast(2)
|
||||
|
||||
val kind = FunctionClassKind.SuspendFunction
|
||||
return ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(ClassId(kind.packageFqName, kind.numberedClassName(valueParameters.size))),
|
||||
(valueParameters + suspendReturnType).toTypedArray(),
|
||||
isNullable, attributes
|
||||
)
|
||||
}
|
||||
|
||||
private fun createSuspendFunctionType(
|
||||
//annotations: Annotations, TODO?
|
||||
functionTypeConstructor: ConeClassLikeLookupTag,
|
||||
arguments: Array<ConeTypeProjection>,
|
||||
isNullable: Boolean,
|
||||
attributes: ConeAttributes
|
||||
): ConeClassLikeType {
|
||||
val result =
|
||||
when (functionTypeConstructor.toSymbol(session)!!.firUnsafe<FirTypeParameterRefsOwner>().typeParameters.size - arguments.size) {
|
||||
0 -> createSuspendFunctionTypeForBasicCase(/* annotations, */ functionTypeConstructor, arguments, isNullable, attributes)
|
||||
// This case for types written by eap compiler 1.1
|
||||
1 -> {
|
||||
val arity = arguments.size - 1
|
||||
if (arity >= 0) {
|
||||
val kind = FunctionClassKind.SuspendFunction
|
||||
ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(ClassId(kind.packageFqName, kind.numberedClassName(arity))),
|
||||
arguments,
|
||||
isNullable,
|
||||
attributes
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
return result ?: ConeClassErrorType(
|
||||
ConeSimpleDiagnostic(
|
||||
"Bad suspend function in metadata with constructor: $functionTypeConstructor",
|
||||
DiagnosticKind.DeserializationError
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun typeSymbol(proto: ProtoBuf.Type): ConeClassifierLookupTag? {
|
||||
|
||||
return when {
|
||||
proto.hasClassName() -> computeClassifier(proto.className)
|
||||
proto.hasTypeAliasName() -> computeClassifier(proto.typeAliasName)
|
||||
proto.hasTypeParameter() -> typeParameterSymbol(proto.typeParameter)
|
||||
proto.hasTypeParameterName() -> {
|
||||
val name = nameResolver.getString(proto.typeParameterName)
|
||||
typeParameterNames[name]?.toLookupTag()
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun typeArgument(typeArgumentProto: ProtoBuf.Type.Argument): ConeTypeProjection {
|
||||
if (typeArgumentProto.projection == ProtoBuf.Type.Argument.Projection.STAR) {
|
||||
return ConeStarProjection
|
||||
}
|
||||
|
||||
val variance = ProtoEnumFlags.variance(typeArgumentProto.projection)
|
||||
val type = typeArgumentProto.type(typeTable)
|
||||
?: return ConeKotlinErrorType(ConeSimpleDiagnostic("No type recorded", DiagnosticKind.DeserializationError))
|
||||
|
||||
// TODO: check that here we don't have any attributes
|
||||
val coneType = type(type, ConeAttributes.Empty)
|
||||
return coneType.toTypeProjection(variance)
|
||||
}
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* 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.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
|
||||
val CONTINUATION_INTERFACE_CLASS_ID = ClassId.topLevel(StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE)
|
||||
+324
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* 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.resolve.providers.impl
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildTypeParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
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
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.constructClassType
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoBasedClassDataFinder
|
||||
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.getOrPut
|
||||
import java.io.InputStream
|
||||
|
||||
class FirBuiltinSymbolProvider(session: FirSession, val kotlinScopeProvider: KotlinScopeProvider) : FirSymbolProvider(session) {
|
||||
|
||||
private data class SyntheticFunctionalInterfaceSymbolKey(val kind: FunctionClassKind, val arity: Int)
|
||||
|
||||
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
|
||||
private val syntheticFunctionalInterfaceSymbols = mutableMapOf<SyntheticFunctionalInterfaceSymbolKey, FirRegularClassSymbol>()
|
||||
|
||||
private fun loadBuiltIns(): List<BuiltInsPackageFragment> {
|
||||
val classLoader = this::class.java.classLoader
|
||||
val streamProvider = { path: String -> classLoader?.getResourceAsStream(path) ?: ClassLoader.getSystemResourceAsStream(path) }
|
||||
val packageFqNames = StandardNames.BUILT_INS_PACKAGE_FQ_NAMES
|
||||
|
||||
return packageFqNames.map { fqName ->
|
||||
val resourcePath = BuiltInSerializerProtocol.getBuiltInsFilePath(fqName)
|
||||
val inputStream = streamProvider(resourcePath) ?: throw IllegalStateException("Resource not found in classpath: $resourcePath")
|
||||
BuiltInsPackageFragment(inputStream, fqName, session, kotlinScopeProvider)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPackage(fqName: FqName): FqName? {
|
||||
if (allPackageFragments.containsKey(fqName)) return fqName
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? {
|
||||
return allPackageFragments[classId.packageFqName]?.firstNotNullResult {
|
||||
it.getClassLikeSymbolByFqName(classId)
|
||||
} ?: trySyntheticFunctionalInterface(classId)
|
||||
}
|
||||
|
||||
private fun trySyntheticFunctionalInterface(classId: ClassId): FirRegularClassSymbol? {
|
||||
return with(classId) {
|
||||
val className = relativeClassName.asString()
|
||||
val kind = FunctionClassKind.byClassNamePrefix(packageFqName, className) ?: return@with null
|
||||
val prefix = kind.classNamePrefix
|
||||
val arity = className.substring(prefix.length).toIntOrNull() ?: return null
|
||||
syntheticFunctionalInterfaceSymbols.getOrPut(SyntheticFunctionalInterfaceSymbolKey(kind, arity)) {
|
||||
FirRegularClassSymbol(this).apply symbol@{
|
||||
buildRegularClass klass@{
|
||||
session = this@FirBuiltinSymbolProvider.session
|
||||
origin = FirDeclarationOrigin.Synthetic
|
||||
name = relativeClassName.shortName()
|
||||
status = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Public,
|
||||
Modality.ABSTRACT
|
||||
).apply {
|
||||
isExpect = false
|
||||
isActual = false
|
||||
isInner = false
|
||||
isCompanion = false
|
||||
isData = false
|
||||
isInline = false
|
||||
}
|
||||
classKind = ClassKind.INTERFACE
|
||||
scopeProvider = kotlinScopeProvider
|
||||
symbol = this@symbol
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
typeParameters.addAll(
|
||||
(1..arity).map {
|
||||
buildTypeParameter {
|
||||
session = this@FirBuiltinSymbolProvider.session
|
||||
origin = FirDeclarationOrigin.Synthetic
|
||||
name = Name.identifier("P$it")
|
||||
symbol = FirTypeParameterSymbol()
|
||||
variance = Variance.IN_VARIANCE
|
||||
isReified = false
|
||||
bounds += session.builtinTypes.nullableAnyType
|
||||
}
|
||||
},
|
||||
)
|
||||
typeParameters.add(
|
||||
buildTypeParameter {
|
||||
session = this@FirBuiltinSymbolProvider.session
|
||||
origin = FirDeclarationOrigin.Synthetic
|
||||
name = Name.identifier("R")
|
||||
symbol = FirTypeParameterSymbol()
|
||||
variance = Variance.OUT_VARIANCE
|
||||
isReified = false
|
||||
bounds += session.builtinTypes.nullableAnyType
|
||||
},
|
||||
)
|
||||
val name = OperatorNameConventions.INVOKE
|
||||
val functionStatus = FirResolvedDeclarationStatusImpl(
|
||||
Visibilities.Public,
|
||||
Modality.ABSTRACT
|
||||
).apply {
|
||||
isExpect = false
|
||||
isActual = false
|
||||
isOverride = false
|
||||
isOperator = true
|
||||
isInfix = false
|
||||
isInline = false
|
||||
isTailRec = false
|
||||
isExternal = false
|
||||
isSuspend =
|
||||
kind == FunctionClassKind.SuspendFunction ||
|
||||
kind == FunctionClassKind.KSuspendFunction
|
||||
}
|
||||
val typeArguments = typeParameters.map {
|
||||
buildResolvedTypeRef {
|
||||
type = ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
|
||||
}
|
||||
}
|
||||
val superKind: FunctionClassKind? = when (kind) {
|
||||
FunctionClassKind.KFunction -> FunctionClassKind.Function
|
||||
FunctionClassKind.KSuspendFunction -> FunctionClassKind.SuspendFunction
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun createSuperType(
|
||||
kind: FunctionClassKind,
|
||||
): FirResolvedTypeRef {
|
||||
return buildResolvedTypeRef {
|
||||
type = ConeClassLikeLookupTagImpl(kind.classId(arity))
|
||||
.constructClassType(typeArguments.map { it.type }.toTypedArray(), isNullable = false)
|
||||
}
|
||||
}
|
||||
|
||||
superTypeRefs += when (kind) {
|
||||
FunctionClassKind.Function -> listOf(
|
||||
buildResolvedTypeRef {
|
||||
type = ConeClassLikeLookupTagImpl(StandardClassIds.Function)
|
||||
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
|
||||
}
|
||||
)
|
||||
|
||||
FunctionClassKind.SuspendFunction -> listOf(
|
||||
buildResolvedTypeRef {
|
||||
type = ConeClassLikeLookupTagImpl(StandardClassIds.Function)
|
||||
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
|
||||
}
|
||||
)
|
||||
|
||||
FunctionClassKind.KFunction -> listOf(
|
||||
buildResolvedTypeRef {
|
||||
type = ConeClassLikeLookupTagImpl(StandardClassIds.KFunction)
|
||||
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
|
||||
},
|
||||
createSuperType(FunctionClassKind.Function)
|
||||
)
|
||||
|
||||
FunctionClassKind.KSuspendFunction -> listOf(
|
||||
buildResolvedTypeRef {
|
||||
type = ConeClassLikeLookupTagImpl(StandardClassIds.KFunction)
|
||||
.constructClassType(arrayOf(typeArguments.last().type), isNullable = false)
|
||||
},
|
||||
createSuperType(FunctionClassKind.SuspendFunction)
|
||||
)
|
||||
}
|
||||
addDeclaration(
|
||||
buildSimpleFunction {
|
||||
session = this@FirBuiltinSymbolProvider.session
|
||||
origin = FirDeclarationOrigin.Synthetic
|
||||
returnTypeRef = typeArguments.last()
|
||||
this.name = name
|
||||
status = functionStatus
|
||||
symbol = FirNamedFunctionSymbol(
|
||||
CallableId(packageFqName, relativeClassName, name),
|
||||
// set overriddenSymbol for "invoke" of KFunction/KSuspendFunction
|
||||
superKind != null, superKind?.getInvoke(arity)
|
||||
)
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
valueParameters += typeArguments.dropLast(1).mapIndexed { index, typeArgument ->
|
||||
val parameterName = Name.identifier("p${index + 1}")
|
||||
buildValueParameter {
|
||||
session = this@FirBuiltinSymbolProvider.session
|
||||
origin = FirDeclarationOrigin.Synthetic
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
returnTypeRef = typeArgument
|
||||
this.name = parameterName
|
||||
symbol = FirVariableSymbol(parameterName)
|
||||
defaultValue = null
|
||||
isCrossinline = false
|
||||
isNoinline = false
|
||||
isVararg = false
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find the symbol for "invoke" in the function class
|
||||
private fun FunctionClassKind.getInvoke(arity: Int): FirNamedFunctionSymbol? {
|
||||
val functionClass = getClassLikeSymbolByFqName(classId(arity)) ?: return null
|
||||
val invoke =
|
||||
functionClass.fir.declarations.find { it is FirSimpleFunction && it.name == OperatorNameConventions.INVOKE } ?: return null
|
||||
return (invoke as FirSimpleFunction).symbol as? FirNamedFunctionSymbol
|
||||
}
|
||||
|
||||
private fun FunctionClassKind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
|
||||
|
||||
@FirSymbolProviderInternals
|
||||
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
||||
allPackageFragments[packageFqName]?.flatMapTo(destination) {
|
||||
it.getTopLevelCallableSymbols(name)
|
||||
}
|
||||
}
|
||||
|
||||
private class BuiltInsPackageFragment(
|
||||
stream: InputStream, val fqName: FqName, val session: FirSession,
|
||||
val kotlinScopeProvider: KotlinScopeProvider,
|
||||
) {
|
||||
lateinit var version: BuiltInsBinaryVersion
|
||||
|
||||
val packageProto: ProtoBuf.PackageFragment = run {
|
||||
|
||||
version = BuiltInsBinaryVersion.readFrom(stream)
|
||||
|
||||
if (!version.isCompatible()) {
|
||||
// TODO: report a proper diagnostic
|
||||
throw UnsupportedOperationException(
|
||||
"Kotlin built-in definition format version is not supported: " +
|
||||
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
|
||||
"Please update Kotlin",
|
||||
)
|
||||
}
|
||||
|
||||
ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
|
||||
}
|
||||
|
||||
private val nameResolver = NameResolverImpl(packageProto.strings, packageProto.qualifiedNames)
|
||||
|
||||
val classDataFinder = ProtoBasedClassDataFinder(packageProto, nameResolver, version) { SourceElement.NO_SOURCE }
|
||||
|
||||
private val memberDeserializer by lazy {
|
||||
FirDeserializationContext.createForPackage(
|
||||
fqName, packageProto.`package`, nameResolver, session,
|
||||
FirBuiltinAnnotationDeserializer(session),
|
||||
FirConstDeserializer(session),
|
||||
containerSource = null
|
||||
).memberDeserializer
|
||||
}
|
||||
|
||||
private val lookup = mutableMapOf<ClassId, FirRegularClassSymbol>()
|
||||
|
||||
fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? =
|
||||
findAndDeserializeClass(classId)
|
||||
|
||||
private fun findAndDeserializeClass(
|
||||
classId: ClassId,
|
||||
parentContext: FirDeserializationContext? = null,
|
||||
): FirRegularClassSymbol? {
|
||||
val classIdExists = classId in classDataFinder.allClassIds
|
||||
if (!classIdExists) return null
|
||||
return lookup.getOrPut(classId, { FirRegularClassSymbol(classId) }) { symbol ->
|
||||
val classData = classDataFinder.findClassData(classId)!!
|
||||
val classProto = classData.classProto
|
||||
|
||||
deserializeClassToSymbol(
|
||||
classId, classProto, symbol, nameResolver, session,
|
||||
null, kotlinScopeProvider, parentContext,
|
||||
null,
|
||||
this::findAndDeserializeClass,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getTopLevelCallableSymbols(name: Name): List<FirCallableSymbol<*>> {
|
||||
return packageProto.`package`.functionList.filter { nameResolver.getName(it.name) == name }.map {
|
||||
memberDeserializer.loadFunction(it).symbol
|
||||
}
|
||||
}
|
||||
|
||||
fun getAllCallableNames(): Set<Name> {
|
||||
return packageProto.`package`.functionList.mapTo(mutableSetOf()) { nameResolver.getName(it.name) }
|
||||
}
|
||||
|
||||
fun getAllClassNames(): Set<Name> {
|
||||
return classDataFinder.allClassIds.mapTo(mutableSetOf()) { it.shortClassName }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user