[Linker] Add option to control scope of DescriptorByIdSignatureFinder

Currently DescriptorByIdSignatureFinder performs lookup of descriptor
not only in the given module but also in its dependencies.
This behaviour is incorrect if we have some kind of
relation (e.g. mapping) between moduleDescriptor and found descriptor.
Thus, we add a handle to control search scope.
This commit is contained in:
Sergey Bogolepov
2020-04-21 13:15:29 +07:00
parent 318d4d17ba
commit 0ed0152ee0
2 changed files with 51 additions and 6 deletions
@@ -6,10 +6,34 @@
package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.KotlinMangler
class DescriptorByIdSignatureFinder(private val moduleDescriptor: ModuleDescriptor, private val mangler: KotlinMangler.DescriptorMangler) {
class DescriptorByIdSignatureFinder(
private val moduleDescriptor: ModuleDescriptor,
private val mangler: KotlinMangler.DescriptorMangler,
private val lookupMode: LookupMode
) {
init {
assert(lookupMode != LookupMode.MODULE_ONLY || moduleDescriptor is ModuleDescriptorImpl)
}
/**
* Sets search scope for [findDescriptorBySignature].
*/
enum class LookupMode {
/**
* Perform search of descriptor in [moduleDescriptor] and its dependencies.
*/
MODULE_WITH_DEPENDENCIES,
/**
* Perform search of descriptor only in [moduleDescriptor].
*/
MODULE_ONLY
}
fun findDescriptorBySignature(signature: IdSignature): DeclarationDescriptor? = when (signature) {
is IdSignature.AccessorSignature -> findDescriptorForAccessorSignature(signature)
is IdSignature.PublicSignature -> findDescriptorForPublicSignature(signature)
@@ -24,11 +48,29 @@ class DescriptorByIdSignatureFinder(private val moduleDescriptor: ModuleDescript
}
}
private fun performLookup(signature: IdSignature.PublicSignature): Collection<DeclarationDescriptor> {
val declarationName = signature.declarationFqn.pathSegments().first()
return when (lookupMode) {
LookupMode.MODULE_WITH_DEPENDENCIES -> {
moduleDescriptor
.getPackage(signature.packageFqName())
.memberScope
.getContributedDescriptors { name -> name == declarationName }
}
LookupMode.MODULE_ONLY -> {
(moduleDescriptor as ModuleDescriptorImpl)
.packageFragmentProviderForModuleContentWithoutDependencies
.getPackageFragments(signature.packageFqName())
.map { it.getMemberScope() }
.flatMap { it.getContributedDescriptors { name -> name == declarationName } }
}
}
}
private fun findDescriptorForPublicSignature(signature: IdSignature.PublicSignature): DeclarationDescriptor? {
val packageDescriptor = moduleDescriptor.getPackage(signature.packageFqName())
val toplevelDescriptors = performLookup(signature)
.ifEmpty { return null }
val pathSegments = signature.declarationFqn.pathSegments()
val toplevelDescriptors = packageDescriptor.memberScope.getContributedDescriptors { name -> name == pathSegments.first() }
.filter { it.name == pathSegments.first() }
val candidates = pathSegments.drop(1).fold(toplevelDescriptors) { acc, current ->
acc.flatMap { container ->
val classDescriptor = container as? ClassDescriptor
@@ -50,7 +92,7 @@ class DescriptorByIdSignatureFinder(private val moduleDescriptor: ModuleDescript
}
}
private fun findDescriptorByHash(candidates: List<DeclarationDescriptor>, id: Long?): DeclarationDescriptor? =
private fun findDescriptorByHash(candidates: Collection<DeclarationDescriptor>, id: Long?): DeclarationDescriptor? =
candidates.firstOrNull { candidate ->
if (id == null) {
// We don't compute id for typealiases and classes.
@@ -111,7 +111,10 @@ class JvmIrLinker(currentModule: ModuleDescriptor?, logger: LoggingContext, buil
// TODO: implement proper check whether `idSig` belongs to this module
override fun contains(idSig: IdSignature): Boolean = true
private val descriptorFinder = DescriptorByIdSignatureFinder(moduleDescriptor, manglerDesc)
private val descriptorFinder = DescriptorByIdSignatureFinder(
moduleDescriptor, manglerDesc,
DescriptorByIdSignatureFinder.LookupMode.MODULE_ONLY
)
private fun resolveDescriptor(idSig: IdSignature): DeclarationDescriptor {
return descriptorFinder.findDescriptorBySignature(idSig) ?: error("No descriptor found for $idSig")