[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:
+47
-5
@@ -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.
|
||||
|
||||
+4
-1
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user