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) {
packageFragment.components = components
packageFragment.initialize(components)
}
return provider
@@ -32,7 +32,7 @@ abstract class AbstractDeserializedPackageFragmentProvider(
private val fragments = storageManager.createMemoizedFunctionWithNullableValues<FqName, PackageFragmentDescriptor> { fqName ->
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.name.FqName
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.storage.StorageManager
import javax.inject.Inject
abstract class DeserializedPackageFragment(
fqName: FqName,
protected val storageManager: StorageManager,
module: ModuleDescriptor
) : 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
protected abstract fun computeMemberScope(): MemberScope
override fun getMemberScope() = memberScope()
open fun hasTopLevelClass(name: Name): Boolean {
val scope = getMemberScope()
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.deserialization.NameResolverImpl
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.DeserializedPackageMemberScope
import org.jetbrains.kotlin.storage.StorageManager
abstract class DeserializedPackageFragmentImpl(
fqName: FqName,
storageManager: StorageManager,
module: ModuleDescriptor,
protected val proto: ProtoBuf.PackageFragment,
private val containerSource: DeserializedContainerSource?
fqName: FqName,
storageManager: StorageManager,
module: ModuleDescriptor,
protected val proto: ProtoBuf.PackageFragment,
private val containerSource: DeserializedContainerSource?
) : DeserializedPackageFragment(fqName, storageManager, module) {
protected val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
override val classDataFinder = ProtoBasedClassDataFinder(proto, nameResolver) { containerSource ?: SourceElement.NO_SOURCE }
override fun computeMemberScope() =
DeserializedPackageMemberScope(
this, proto.`package`, nameResolver, containerSource, components,
classNames = {
classDataFinder.allClassIds.filter { classId ->
!classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST
}.map { it.shortClassName }
}
)
private lateinit var _memberScope: MemberScope
override fun initialize(components: DeserializationComponents) {
_memberScope = DeserializedPackageMemberScope(
this, proto.`package`, nameResolver, containerSource, components,
classNames = {
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
// with top level callables and type aliases (but no classes) only from that part
val packageParts = packagePartProvider.findMetadataPackageParts(fqName.asString())
@@ -115,6 +123,8 @@ class MetadataPackageFragment(
return ChainedMemberScope.create("Metadata scope", scopes)
}
override fun getMemberScope() = memberScope()
override fun hasTopLevelClass(name: Name): Boolean {
// TODO: check if the corresponding file exists
return true
@@ -46,8 +46,11 @@ class KotlinJavascriptPackageFragment(
}
}
private val annotationDeserializer: AnnotationDeserializer by storageManager.createLazyValue {
AnnotationDeserializer(module, components.notFoundClasses)
private lateinit var annotationDeserializer: AnnotationDeserializer
override fun initialize(components: DeserializationComponents) {
super.initialize(components)
this.annotationDeserializer = AnnotationDeserializer(components.moduleDescriptor, components.notFoundClasses)
}
fun getContainingFileAnnotations(descriptor: DeclarationDescriptor): List<AnnotationDescriptor> {
@@ -80,7 +80,7 @@ fun createKotlinJavascriptPackageFragmentProvider(
)
for (packageFragment in packageFragments.filterIsInstance<KotlinJavascriptPackageFragment>()) {
packageFragment.components = components
packageFragment.initialize(components)
}
return provider