Pull down some implementation details from DeserializedPackageFragment

- DeserializedPackageFragmentImpl doesn't actually need member scope to be lazy
in a sense of optimization. It was only necessary for breaking
initialization cycle: DeserializationComponents <-> DeserializedPackageFragment
- For MetadataPackageFragment it might be useful to have
member scope actually lazy since it has O(n) complexity when n is a number
of package parts

This change is helpful for avoidance of storing reference to package-proto

 #KT-24513 In Progress
This commit is contained in:
Denis Zharkov
2018-05-30 14:49:15 +03:00
parent 99b44faf5a
commit 0a3e8fbe66
7 changed files with 40 additions and 30 deletions
@@ -88,7 +88,7 @@ class BuiltInsLoaderImpl : BuiltInsLoader {
) )
for (packageFragment in packageFragments) { for (packageFragment in packageFragments) {
packageFragment.components = components packageFragment.initialize(components)
} }
return provider return provider
@@ -32,7 +32,7 @@ abstract class AbstractDeserializedPackageFragmentProvider(
private val fragments = storageManager.createMemoizedFunctionWithNullableValues<FqName, PackageFragmentDescriptor> { fqName -> private val fragments = storageManager.createMemoizedFunctionWithNullableValues<FqName, PackageFragmentDescriptor> { fqName ->
findPackage(fqName)?.apply { findPackage(fqName)?.apply {
components = this@AbstractDeserializedPackageFragmentProvider.components initialize(components)
} }
} }
@@ -20,28 +20,19 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberScope import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberScope
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import javax.inject.Inject
abstract class DeserializedPackageFragment( abstract class DeserializedPackageFragment(
fqName: FqName, fqName: FqName,
protected val storageManager: StorageManager, protected val storageManager: StorageManager,
module: ModuleDescriptor module: ModuleDescriptor
) : PackageFragmentDescriptorImpl(module, fqName) { ) : PackageFragmentDescriptorImpl(module, fqName) {
// component dependency cycle
@set:Inject
lateinit var components: DeserializationComponents
private val memberScope = storageManager.createLazyValue { computeMemberScope() } abstract fun initialize(components: DeserializationComponents)
abstract val classDataFinder: ClassDataFinder abstract val classDataFinder: ClassDataFinder
protected abstract fun computeMemberScope(): MemberScope
override fun getMemberScope() = memberScope()
open fun hasTopLevelClass(name: Name): Boolean { open fun hasTopLevelClass(name: Name): Boolean {
val scope = getMemberScope() val scope = getMemberScope()
return scope is DeserializedMemberScope && name in scope.classNames return scope is DeserializedMemberScope && name in scope.classNames
@@ -21,28 +21,34 @@ import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
abstract class DeserializedPackageFragmentImpl( abstract class DeserializedPackageFragmentImpl(
fqName: FqName, fqName: FqName,
storageManager: StorageManager, storageManager: StorageManager,
module: ModuleDescriptor, module: ModuleDescriptor,
protected val proto: ProtoBuf.PackageFragment, protected val proto: ProtoBuf.PackageFragment,
private val containerSource: DeserializedContainerSource? private val containerSource: DeserializedContainerSource?
) : DeserializedPackageFragment(fqName, storageManager, module) { ) : DeserializedPackageFragment(fqName, storageManager, module) {
protected val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames) protected val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
override val classDataFinder = ProtoBasedClassDataFinder(proto, nameResolver) { containerSource ?: SourceElement.NO_SOURCE } override val classDataFinder = ProtoBasedClassDataFinder(proto, nameResolver) { containerSource ?: SourceElement.NO_SOURCE }
override fun computeMemberScope() = private lateinit var _memberScope: MemberScope
DeserializedPackageMemberScope(
this, proto.`package`, nameResolver, containerSource, components, override fun initialize(components: DeserializationComponents) {
classNames = { _memberScope = DeserializedPackageMemberScope(
classDataFinder.allClassIds.filter { classId -> this, proto.`package`, nameResolver, containerSource, components,
!classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST classNames = {
}.map { it.shortClassName } classDataFinder.allClassIds.filter { classId ->
} !classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST
) }.map { it.shortClassName }
}
)
}
override fun getMemberScope(): MemberScope = _memberScope
} }
@@ -87,7 +87,15 @@ class MetadataPackageFragment(
} }
} }
override fun computeMemberScope(): MemberScope { private lateinit var components: DeserializationComponents
override fun initialize(components: DeserializationComponents) {
this.components = components
}
private val memberScope = storageManager.createLazyValue { computeMemberScope() }
private fun computeMemberScope(): MemberScope {
// For each .kotlin_metadata file which represents a package part, add a separate deserialized scope // For each .kotlin_metadata file which represents a package part, add a separate deserialized scope
// with top level callables and type aliases (but no classes) only from that part // with top level callables and type aliases (but no classes) only from that part
val packageParts = packagePartProvider.findMetadataPackageParts(fqName.asString()) val packageParts = packagePartProvider.findMetadataPackageParts(fqName.asString())
@@ -115,6 +123,8 @@ class MetadataPackageFragment(
return ChainedMemberScope.create("Metadata scope", scopes) return ChainedMemberScope.create("Metadata scope", scopes)
} }
override fun getMemberScope() = memberScope()
override fun hasTopLevelClass(name: Name): Boolean { override fun hasTopLevelClass(name: Name): Boolean {
// TODO: check if the corresponding file exists // TODO: check if the corresponding file exists
return true return true
@@ -46,8 +46,11 @@ class KotlinJavascriptPackageFragment(
} }
} }
private val annotationDeserializer: AnnotationDeserializer by storageManager.createLazyValue { private lateinit var annotationDeserializer: AnnotationDeserializer
AnnotationDeserializer(module, components.notFoundClasses)
override fun initialize(components: DeserializationComponents) {
super.initialize(components)
this.annotationDeserializer = AnnotationDeserializer(components.moduleDescriptor, components.notFoundClasses)
} }
fun getContainingFileAnnotations(descriptor: DeclarationDescriptor): List<AnnotationDescriptor> { fun getContainingFileAnnotations(descriptor: DeclarationDescriptor): List<AnnotationDescriptor> {
@@ -80,7 +80,7 @@ fun createKotlinJavascriptPackageFragmentProvider(
) )
for (packageFragment in packageFragments.filterIsInstance<KotlinJavascriptPackageFragment>()) { for (packageFragment in packageFragments.filterIsInstance<KotlinJavascriptPackageFragment>()) {
packageFragment.components = components packageFragment.initialize(components)
} }
return provider return provider