[FIR JS] Prepare the infrastructure for FIR JS tests
This commit is contained in:
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.session
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
|
||||
import org.jetbrains.kotlin.library.metadata.KlibMetadataSerializerProtocol
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
|
||||
|
||||
class KlibBasedAnnotationDeserializer(
|
||||
session: FirSession
|
||||
) : AbstractAnnotationDeserializer(session) {
|
||||
override val protocol: SerializerExtensionProtocol
|
||||
get() = KlibMetadataSerializerProtocol
|
||||
|
||||
override fun loadTypeAnnotations(typeProto: ProtoBuf.Type, nameResolver: NameResolver): List<FirAnnotation> {
|
||||
val annotations = typeProto.getExtension(KlibMetadataProtoBuf.typeAnnotation).orEmpty()
|
||||
return annotations.map { deserializeAnnotation(it, nameResolver) }
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.session
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SourceFile
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.deserialization.*
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||
import org.jetbrains.kotlin.library.metadata.KlibMetadataClassDataFinder
|
||||
import org.jetbrains.kotlin.library.resolver.KotlinResolvedLibrary
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
import java.nio.file.Paths
|
||||
|
||||
class KlibBasedSymbolProvider(
|
||||
session: FirSession,
|
||||
moduleDataProvider: ModuleDataProvider,
|
||||
kotlinScopeProvider: FirKotlinScopeProvider,
|
||||
private val resolvedLibrary: KotlinResolvedLibrary,
|
||||
defaultDeserializationOrigin: FirDeclarationOrigin = FirDeclarationOrigin.Library
|
||||
) : AbstractFirDeserializedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, defaultDeserializationOrigin) {
|
||||
private val moduleHeader by lazy {
|
||||
resolvedLibrary.loadModuleHeader(resolvedLibrary.library)
|
||||
}
|
||||
|
||||
private val fragmentNameList by lazy {
|
||||
moduleHeader.packageFragmentNameList.toSet()
|
||||
}
|
||||
|
||||
private val annotationDeserializer = KlibBasedAnnotationDeserializer(session)
|
||||
private val constDeserializer = FirConstDeserializer(session)
|
||||
private val deserializationConfiguration = CompilerDeserializationConfiguration(session.languageVersionSettings)
|
||||
private val cachedFragments = mutableMapOf<Pair<String, String>, ProtoBuf.PackageFragment>()
|
||||
|
||||
private fun getPackageFragment(packageStringName: String, packageMetadataPart: String): ProtoBuf.PackageFragment {
|
||||
return cachedFragments.getOrPut(packageStringName to packageMetadataPart) {
|
||||
resolvedLibrary.loadPackageFragment(resolvedLibrary.library, packageStringName, packageMetadataPart)
|
||||
}
|
||||
}
|
||||
|
||||
override fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData> {
|
||||
val packageStringName = packageFqName.asString()
|
||||
|
||||
if (packageStringName !in fragmentNameList) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
return resolvedLibrary.library.packageMetadataParts(packageStringName).mapNotNull {
|
||||
val fragment = getPackageFragment(packageStringName, it)
|
||||
|
||||
val libraryPath = Paths.get(resolvedLibrary.library.libraryName)
|
||||
val moduleData = moduleDataProvider.getModuleData(libraryPath) ?: return@mapNotNull null
|
||||
val packageProto = fragment.`package`
|
||||
|
||||
val nameResolver = NameResolverImpl(
|
||||
fragment.strings,
|
||||
fragment.qualifiedNames,
|
||||
)
|
||||
|
||||
PackagePartsCacheData(
|
||||
packageProto,
|
||||
FirDeserializationContext.createForPackage(
|
||||
packageFqName, packageProto, nameResolver, moduleData,
|
||||
annotationDeserializer,
|
||||
constDeserializer,
|
||||
null,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun extractClassMetadata(classId: ClassId, parentContext: FirDeserializationContext?): ClassMetadataFindResult? {
|
||||
val packageStringName = classId.packageFqName.asString()
|
||||
|
||||
if (packageStringName !in fragmentNameList) {
|
||||
return null
|
||||
}
|
||||
|
||||
resolvedLibrary.library.packageMetadataParts(packageStringName).forEach {
|
||||
val libraryPath = Paths.get(resolvedLibrary.library.libraryName)
|
||||
val fragment = getPackageFragment(packageStringName, it)
|
||||
|
||||
val nameResolver = NameResolverImpl(
|
||||
fragment.strings,
|
||||
fragment.qualifiedNames,
|
||||
)
|
||||
|
||||
val finder = KlibMetadataClassDataFinder(fragment, nameResolver)
|
||||
val classProto = finder.findClassData(classId)?.classProto ?: return@forEach
|
||||
|
||||
val source = object : DeserializedContainerSource {
|
||||
override val incompatibility: IncompatibleVersionErrorData<*>? = null
|
||||
override val isPreReleaseInvisible =
|
||||
deserializationConfiguration.reportErrorsOnPreReleaseDependencies && (moduleHeader.flags and 1) != 0
|
||||
override val abiStability = DeserializedContainerAbiStability.STABLE
|
||||
override val presentableString = "Package '${classId.packageFqName}'"
|
||||
|
||||
override fun getContainingFile() = SourceFile.NO_SOURCE_FILE
|
||||
}
|
||||
|
||||
return ClassMetadataFindResult.Metadata(
|
||||
nameResolver,
|
||||
classProto,
|
||||
annotationDeserializer,
|
||||
moduleDataProvider.getModuleData(libraryPath),
|
||||
source,
|
||||
classPostProcessor = {}
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun isNewPlaceForBodyGeneration(classProto: ProtoBuf.Class) = false
|
||||
|
||||
override fun getPackage(fqName: FqName): FqName? {
|
||||
return if (fqName.toString() in fragmentNameList) {
|
||||
fqName
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user