Load definitions of symbols from .kotlin_metadata files

Extract AbstractDeserializedPackageFragmentProvider out of
JvmBuiltInsPackageFragmentProvider and implement it a little bit differently in
MetadataPackageFragmentProvider. The main difference is in how the package
fragment scope is constructed: for built-ins, it's just a single scope that
loads everything from one protobuf message. For metadata, package scope can
consist of many files, some of which store information about classes and others
are similar to package parts on JVM, so a ChainedMemberScope instance is
created.

Introduce a bunch of interfaces/methods to deliver the needed behavior to the
'deserialization' module which is not JVM-specific and does not depend on the
compiler code: MetadataFinderFactory,
PackagePartProvider#findMetadataPackageParts, KotlinMetadataFinder#findMetadata.
Note that these declarations are currently only implemented in the compiler; no
metadata package parts/fragments will be found in IDE or reflection
This commit is contained in:
Alexander Udalov
2016-11-16 11:47:05 +03:00
parent 32792c5ce4
commit bfb7b21472
21 changed files with 320 additions and 57 deletions
@@ -18,15 +18,11 @@ package org.jetbrains.kotlin.builtins
import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.singletonOrEmptyList
class JvmBuiltInsPackageFragmentProvider(
storageManager: StorageManager,
@@ -35,22 +31,12 @@ class JvmBuiltInsPackageFragmentProvider(
notFoundClasses: NotFoundClasses,
additionalClassPartsProvider: AdditionalClassPartsProvider,
platformDependentDeclarationFilter: PlatformDependentDeclarationFilter
) : PackageFragmentProvider {
private lateinit var components: DeserializationComponents
private val fragments = storageManager.createMemoizedFunctionWithNullableValues<FqName, PackageFragmentDescriptor> { fqName ->
finder.findBuiltInsData(fqName)?.let { inputStream ->
BuiltInsPackageFragment(fqName, storageManager, moduleDescriptor, inputStream).apply {
components = this@JvmBuiltInsPackageFragmentProvider.components
}
}
}
) : AbstractDeserializedPackageFragmentProvider(storageManager, finder, moduleDescriptor) {
init {
components = DeserializationComponents(
storageManager,
moduleDescriptor,
DeserializationConfiguration.Default,
DeserializationConfiguration.Default, // TODO
DeserializedClassDataFinder(this),
AnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, BuiltInSerializerProtocol),
this,
@@ -64,10 +50,10 @@ class JvmBuiltInsPackageFragmentProvider(
),
notFoundClasses, additionalClassPartsProvider, platformDependentDeclarationFilter
)
}
override fun getPackageFragments(fqName: FqName): List<PackageFragmentDescriptor> = fragments(fqName).singletonOrEmptyList()
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> = emptySet()
override fun findPackage(fqName: FqName): DeserializedPackageFragment? =
finder.findBuiltInsData(fqName)?.let { inputStream ->
BuiltInsPackageFragment(fqName, storageManager, moduleDescriptor, inputStream)
}
}
@@ -34,24 +34,20 @@ class ModuleMapping private constructor(val packageFqName2Parts: Map<String, Pac
@JvmField
val EMPTY: ModuleMapping = ModuleMapping(emptyMap(), "EMPTY")
fun create(proto: ByteArray?, debugName: String?): ModuleMapping {
if (proto == null) {
fun create(bytes: ByteArray?, debugName: String?): ModuleMapping {
if (bytes == null) {
return EMPTY
}
val stream = DataInputStream(ByteArrayInputStream(proto))
val stream = DataInputStream(ByteArrayInputStream(bytes))
val version = JvmMetadataVersion(*IntArray(stream.readInt()) { stream.readInt() })
if (version.isCompatible()) {
val parseFrom = JvmPackageTable.PackageTable.parseFrom(stream)
if (parseFrom != null) {
val packageFqNameParts = hashMapOf<String, PackageParts>()
parseFrom.packagePartsList.forEach {
val packageParts = PackageParts(it.packageFqName)
packageFqNameParts.put(it.packageFqName, packageParts)
it.classNameList.forEach {
packageParts.parts.add(it)
}
val packageFqNameParts = hashMapOf<String, PackageParts>().apply {
addParts(this, parseFrom.packagePartsList, PackageParts::parts)
addParts(this, parseFrom.metadataPartsList, PackageParts::metadataParts)
}
return ModuleMapping(packageFqNameParts, debugName ?: "<unknown>")
}
@@ -62,6 +58,19 @@ class ModuleMapping private constructor(val packageFqName2Parts: Map<String, Pac
return EMPTY
}
private inline fun addParts(
result: MutableMap<String, PackageParts>,
partsList: List<JvmPackageTable.PackageParts>,
whichParts: (PackageParts) -> MutableSet<String>
) {
for (proto in partsList) {
PackageParts(proto.packageFqName).apply {
result.put(proto.packageFqName, this)
whichParts(this).addAll(proto.classNameList)
}
}
}
}
}