Move package part-related code from LazyJavaPackageScope to LazyJavaPackageFragment

This commit is contained in:
Alexander Udalov
2015-12-22 02:47:26 +03:00
parent e516b695ae
commit a34aaa5955
8 changed files with 64 additions and 108 deletions
@@ -52,7 +52,7 @@ class LazyJavaPackageFragmentProvider(
override fun getPackageFragments(fqName: FqName) = emptyOrSingletonList(getPackageFragment(fqName))
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean) =
getPackageFragment(fqName)?.getMemberScope()?.getSubPackages().orEmpty()
getPackageFragment(fqName)?.javaScope?.getSubPackages().orEmpty()
fun getClass(javaClass: JavaClass): ClassDescriptor? = c.javaClassResolver.resolveClass(javaClass)
@@ -70,10 +70,7 @@ class LazyJavaPackageFragmentProvider(
if (fqName == null) return null
val packageFragment = getPackageFragment(fqName.parent()) ?: return null
return packageFragment
.getMemberScope()
.findClassifierByJavaClass(javaClass, NoLookupLocation.FROM_JAVA_LOADER)
return getPackageFragment(fqName.parent())?.javaScope?.findClassifierByJavaClass(javaClass, NoLookupLocation.FROM_JAVA_LOADER)
}
}
}
@@ -21,30 +21,59 @@ import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.structure.JavaPackage
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope
import org.jetbrains.kotlin.resolve.scopes.LazyScopeAdapter
import org.jetbrains.kotlin.storage.getValue
class LazyJavaPackageFragment(
private val c: LazyJavaResolverContext,
private val jPackage: JavaPackage
) : PackageFragmentDescriptorImpl(c.module, jPackage.fqName) {
private val scope by c.storageManager.createLazyValue {
internal val binaryClasses by c.storageManager.createLazyValue {
c.components.packageMapper.findPackageParts(fqName.asString()).mapNotNull { partName ->
val classId = ClassId(fqName, Name.identifier(partName))
c.components.kotlinClassFinder.findKotlinClass(classId)?.let { partName to it }
}.toMap()
}
internal val javaScope by c.storageManager.createLazyValue {
LazyJavaPackageScope(c, jPackage, this)
}
internal val kotlinBinaryClasses by c.storageManager.createLazyValue {
c.components.packageMapper.findPackageParts(fqName.asString()).mapNotNull {
val classId = ClassId(fqName, Name.identifier(it))
c.components.kotlinClassFinder.findKotlinClass(classId)
}
private val scope by c.storageManager.createLazyValue {
ChainedMemberScope.create("Java + Deserialized Kotlin scope", listOf(javaScope) + LazyScopeAdapter(c.storageManager.createLazyValue {
ChainedMemberScope.create("Deserialized Kotlin scope", binaryClasses.values.mapNotNull { partClass ->
c.components.deserializedDescriptorResolver.createKotlinPackagePartScope(this, partClass)
})
}))
}
private val partToFacade by c.storageManager.createLazyValue {
val result = hashMapOf<String, String>()
kotlinClasses@for ((partName, kotlinClass) in binaryClasses) {
val header = kotlinClass.classHeader
when (header.kind) {
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
val facadeName = header.multifileClassName ?: continue@kotlinClasses
result[partName] = facadeName.substringAfterLast('/')
}
KotlinClassHeader.Kind.FILE_FACADE -> {
result[partName] = partName
}
else -> {}
}
}
result
}
fun getFacadeSimpleNameForPartSimpleName(partName: String): String? = partToFacade[partName]
override fun getMemberScope() = scope
override fun toString() = "lazy java package fragment: $fqName"
override fun toString() = "Lazy Java package fragment: $fqName"
override fun getSource(): SourceElement {
return KotlinJvmBinaryPackageSourceElement(jPackage, kotlinBinaryClasses)
}
override fun getSource(): SourceElement = KotlinJvmBinaryPackageSourceElement(this)
}
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.storage.NullableLazyValue
import org.jetbrains.kotlin.storage.getValue
class LazyJavaPackageScope(
c: LazyJavaResolverContext,
@@ -47,33 +46,6 @@ class LazyJavaPackageScope(
c.components.finder.knownClassNamesInPackage(ownerDescriptor.fqName)
}
private val partToFacade = c.storageManager.createLazyValue {
val result = hashMapOf<String, String>()
kotlinClasses@for (kotlinClass in ownerDescriptor.kotlinBinaryClasses) {
val header = kotlinClass.classHeader
when (header.kind) {
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
val partName = kotlinClass.classId.shortClassName.asString()
val facadeName = header.multifileClassName ?: continue@kotlinClasses
result[partName] = facadeName.substringAfterLast('/')
}
KotlinClassHeader.Kind.FILE_FACADE -> {
val fileFacadeName = kotlinClass.classId.shortClassName.asString()
result[fileFacadeName] = fileFacadeName
}
else -> {}
}
}
result
}
fun getFacadeSimpleNameForPartSimpleName(partName: String): String? =
partToFacade()[partName]
private val deserializedPackageScope by c.storageManager.createLazyValue {
c.components.deserializedDescriptorResolver.createKotlinPackageScope(ownerDescriptor, ownerDescriptor.kotlinBinaryClasses)
}
private val classes = c.storageManager.createMemoizedFunctionWithNullableValues<FindClassRequest, ClassDescriptor> { request ->
val classId = ClassId(ownerDescriptor.fqName, request.name)
@@ -148,23 +120,7 @@ class LazyJavaPackageScope(
fun findClassifierByJavaClass(javaClass: JavaClass, location: LookupLocation) = findClassifier(javaClass.name, javaClass, location)
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
// We should track lookups here because this scope can be used for kotlin packages too (if it doesn't contain toplevel properties nor functions).
recordLookup(name, location)
return deserializedPackageScope.getContributedVariables(name, NoLookupLocation.FOR_ALREADY_TRACKED)
}
override fun getContributedFunctions(name: Name, location: LookupLocation): List<SimpleFunctionDescriptor> {
// We should track lookups here because this scope can be used for kotlin packages too (if it doesn't contain toplevel properties nor functions).
recordLookup(name, location)
return deserializedPackageScope.getContributedFunctions(name, NoLookupLocation.FOR_ALREADY_TRACKED) + super.getContributedFunctions(name, NoLookupLocation.FOR_ALREADY_TRACKED)
}
override fun addExtraDescriptors(result: MutableSet<DeclarationDescriptor>,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean) {
result.addAll(deserializedPackageScope.getContributedDescriptors(kindFilter, nameFilter))
}
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> = emptyList()
override fun computeMemberIndex(): MemberIndex = object : MemberIndex by EMPTY_MEMBER_INDEX {
// For SAM-constructors
@@ -331,17 +331,9 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS
}
}
addExtraDescriptors(result, kindFilter, nameFilter)
return result.toReadOnlyList()
}
protected open fun addExtraDescriptors(result: MutableSet<DeclarationDescriptor>,
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean) {
// Do nothing
}
protected abstract fun getClassNames(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<Name>
override fun toString() = "Lazy scope for ${ownerDescriptor}"
@@ -20,7 +20,6 @@ import com.google.protobuf.InvalidProtocolBufferException
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.ClassDataWithSource
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
@@ -52,7 +51,7 @@ class DeserializedDescriptorResolver(private val errorReporter: ErrorReporter) {
)
}
private fun createKotlinPackagePartScope(descriptor: PackageFragmentDescriptor, kotlinClass: KotlinJvmBinaryClass): MemberScope? {
fun createKotlinPackagePartScope(descriptor: PackageFragmentDescriptor, kotlinClass: KotlinJvmBinaryClass): MemberScope? {
val data = readData(kotlinClass, KOTLIN_FILE_FACADE_OR_MULTIFILE_CLASS_PART) ?: return null
val strings = kotlinClass.classHeader.strings.sure { "String table not found in $kotlinClass" }
val (nameResolver, packageProto) = parseProto(kotlinClass) {
@@ -65,19 +64,6 @@ class DeserializedDescriptorResolver(private val errorReporter: ErrorReporter) {
}
}
fun createKotlinPackageScope(
descriptor: PackageFragmentDescriptor,
packageParts: List<KotlinJvmBinaryClass>
): MemberScope {
val scopes = packageParts.mapNotNull { callable ->
createKotlinPackagePartScope(descriptor, callable)
}
if (scopes.isEmpty()) {
return MemberScope.Empty
}
return ChainedMemberScope("Member scope for union of package parts data", scopes)
}
internal fun readData(kotlinClass: KotlinJvmBinaryClass, expectedKinds: Set<KotlinClassHeader.Kind>): Array<String>? {
val header = kotlinClass.classHeader
if (!header.metadataVersion.isCompatible()) {
@@ -19,30 +19,22 @@ package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.SourceFile
import org.jetbrains.kotlin.load.java.descriptors.getImplClassNameForDeserialized
import org.jetbrains.kotlin.load.java.structure.JavaPackage
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
class KotlinJvmBinaryPackageSourceElement(
private val jPackage: JavaPackage,
kotlinBinaryClasses: List<KotlinJvmBinaryClass>
private val packageFragment: LazyJavaPackageFragment
) : SourceElement {
private val implClassNameToBinaryClass = run {
val result = hashMapOf<String, KotlinJvmBinaryClass>()
for (kotlinBinaryClass in kotlinBinaryClasses) {
result[kotlinBinaryClass.classId.shortClassName.asString()] = kotlinBinaryClass
}
result
}
override fun toString() = "$packageFragment: ${packageFragment.binaryClasses.keys}"
override fun toString(): String = "Binary package ${jPackage.fqName}: ${implClassNameToBinaryClass.keys}"
override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE
fun getRepresentativeBinaryClass(): KotlinJvmBinaryClass {
return implClassNameToBinaryClass.values.first()
return packageFragment.binaryClasses.values.first()
}
fun getContainingBinaryClass(descriptor: DeserializedCallableMemberDescriptor): KotlinJvmBinaryClass? {
val name = descriptor.getImplClassNameForDeserialized() ?: return null
return implClassNameToBinaryClass[name.asString()]
return packageFragment.binaryClasses[name.asString()]
}
}