ModuleDescriptor: invert "friends" relation
Fixes memory leak caused by modules storing their friends (which can be potentially recreated many times)
This commit is contained in:
@@ -169,37 +169,33 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
|||||||
fun computeDependencyDescriptors(module: M): List<ModuleDescriptorImpl> {
|
fun computeDependencyDescriptors(module: M): List<ModuleDescriptorImpl> {
|
||||||
val orderedDependencies = firstDependency.singletonOrEmptyList() + module.dependencies()
|
val orderedDependencies = firstDependency.singletonOrEmptyList() + module.dependencies()
|
||||||
val dependenciesDescriptors = orderedDependencies.mapTo(ArrayList<ModuleDescriptorImpl>()) {
|
val dependenciesDescriptors = orderedDependencies.mapTo(ArrayList<ModuleDescriptorImpl>()) {
|
||||||
dependencyInfo ->
|
dependencyInfo ->
|
||||||
resolverForProject.descriptorForModule(dependencyInfo as M)
|
resolverForProject.descriptorForModule(dependencyInfo as M)
|
||||||
}
|
}
|
||||||
module.dependencyOnBuiltIns().adjustDependencies(
|
module.dependencyOnBuiltIns().adjustDependencies(
|
||||||
resolverForProject.descriptorForModule(module).builtIns.builtInsModule, dependenciesDescriptors)
|
resolverForProject.descriptorForModule(module).builtIns.builtInsModule, dependenciesDescriptors)
|
||||||
return dependenciesDescriptors
|
return dependenciesDescriptors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun computeModulesWhoseInternalsAreVisible(module: M): Set<ModuleDescriptorImpl> {
|
||||||
|
return module.modulesWhoseInternalsAreVisible().mapTo(LinkedHashSet()) { resolverForProject.descriptorForModule(it as M) }
|
||||||
|
}
|
||||||
|
|
||||||
fun setupModuleDependencies() {
|
fun setupModuleDependencies() {
|
||||||
modules.forEach {
|
modules.forEach {
|
||||||
module ->
|
module ->
|
||||||
resolverForProject.descriptorForModule(module).setDependencies(
|
resolverForProject.descriptorForModule(module).setDependencies(
|
||||||
LazyModuleDependencies(storageManager) { computeDependencyDescriptors(module) }
|
LazyModuleDependencies(
|
||||||
|
storageManager,
|
||||||
|
{ computeDependencyDescriptors(module) },
|
||||||
|
{ computeModulesWhoseInternalsAreVisible(module) }
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupModuleDependencies()
|
setupModuleDependencies()
|
||||||
|
|
||||||
fun addFriends() {
|
|
||||||
modules.forEach {
|
|
||||||
module ->
|
|
||||||
val descriptor = resolverForProject.descriptorForModule(module)
|
|
||||||
module.modulesWhoseInternalsAreVisible().forEach {
|
|
||||||
resolverForProject.descriptorForModule(it as M).addFriend(descriptor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addFriends()
|
|
||||||
|
|
||||||
fun initializeResolverForProject() {
|
fun initializeResolverForProject() {
|
||||||
modules.forEach {
|
modules.forEach {
|
||||||
module ->
|
module ->
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ interface ModuleDescriptor : DeclarationDescriptor, ModuleParameters {
|
|||||||
|
|
||||||
val builtIns: KotlinBuiltIns
|
val builtIns: KotlinBuiltIns
|
||||||
|
|
||||||
fun isFriend(other: ModuleDescriptor): Boolean
|
fun shouldSeeInternalsOf(targetModule: ModuleDescriptor): Boolean
|
||||||
|
|
||||||
override fun substitute(substitutor: TypeSubstitutor): ModuleDescriptor {
|
override fun substitute(substitutor: TypeSubstitutor): ModuleDescriptor {
|
||||||
return this
|
return this
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ public class Visibilities {
|
|||||||
@Override
|
@Override
|
||||||
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
|
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
|
||||||
DeclarationDescriptor fromOrModule = from instanceof PackageViewDescriptor ? ((PackageViewDescriptor) from).getModule() : from;
|
DeclarationDescriptor fromOrModule = from instanceof PackageViewDescriptor ? ((PackageViewDescriptor) from).getModule() : from;
|
||||||
if (!DescriptorUtils.getContainingModule(what).isFriend(DescriptorUtils.getContainingModule(fromOrModule))) return false;
|
if (!DescriptorUtils.getContainingModule(fromOrModule).shouldSeeInternalsOf(DescriptorUtils.getContainingModule(what))) return false;
|
||||||
|
|
||||||
return MODULE_VISIBILITY_HELPER.isInFriendModule(what, from);
|
return MODULE_VISIBILITY_HELPER.isInFriendModule(what, from);
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-18
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.storage.StorageManager
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
import java.util.*
|
import java.lang.IllegalArgumentException
|
||||||
|
|
||||||
class ModuleDescriptorImpl @JvmOverloads constructor(
|
class ModuleDescriptorImpl @JvmOverloads constructor(
|
||||||
moduleName: Name,
|
moduleName: Name,
|
||||||
@@ -56,8 +56,8 @@ class ModuleDescriptorImpl @JvmOverloads constructor(
|
|||||||
|
|
||||||
private val packageFragmentProviderForWholeModuleWithDependencies by lazy {
|
private val packageFragmentProviderForWholeModuleWithDependencies by lazy {
|
||||||
val moduleDependencies = dependencies.sure { "Dependencies of module $id were not set before querying module content" }
|
val moduleDependencies = dependencies.sure { "Dependencies of module $id were not set before querying module content" }
|
||||||
val dependenciesDescriptors = moduleDependencies.descriptors
|
val dependenciesDescriptors = moduleDependencies.allDependencies
|
||||||
assert(this in dependenciesDescriptors) { "Module ${id} is not contained in his own dependencies, this is probably a misconfiguration" }
|
assert(this in dependenciesDescriptors) { "Module $id is not contained in his own dependencies, this is probably a misconfiguration" }
|
||||||
dependenciesDescriptors.forEach {
|
dependenciesDescriptors.forEach {
|
||||||
dependency ->
|
dependency ->
|
||||||
assert(dependency.isInitialized) {
|
assert(dependency.isInitialized) {
|
||||||
@@ -82,7 +82,11 @@ class ModuleDescriptorImpl @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setDependencies(descriptors: List<ModuleDescriptorImpl>) {
|
fun setDependencies(descriptors: List<ModuleDescriptorImpl>) {
|
||||||
setDependencies(ModuleDependenciesImpl(descriptors))
|
setDependencies(ModuleDependenciesImpl(descriptors, emptySet()))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldSeeInternalsOf(targetModule: ModuleDescriptor): Boolean {
|
||||||
|
return this == targetModule || targetModule in dependencies!!.modulesWhoseInternalsAreVisible
|
||||||
}
|
}
|
||||||
|
|
||||||
private val id: String
|
private val id: String
|
||||||
@@ -99,31 +103,28 @@ class ModuleDescriptorImpl @JvmOverloads constructor(
|
|||||||
val packageFragmentProvider: PackageFragmentProvider
|
val packageFragmentProvider: PackageFragmentProvider
|
||||||
get() = packageFragmentProviderForWholeModuleWithDependencies
|
get() = packageFragmentProviderForWholeModuleWithDependencies
|
||||||
|
|
||||||
private val friendModules = LinkedHashSet<ModuleDescriptor>()
|
|
||||||
|
|
||||||
override fun isFriend(other: ModuleDescriptor) = other == this || other in friendModules
|
|
||||||
|
|
||||||
fun addFriend(friend: ModuleDescriptorImpl): Unit {
|
|
||||||
assert(friend != this) { "Attempt to make module $id a friend to itself" }
|
|
||||||
friendModules.add(friend)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun <T> getCapability(capability: ModuleDescriptor.Capability<T>) = capabilities[capability] as? T
|
override fun <T> getCapability(capability: ModuleDescriptor.Capability<T>) = capabilities[capability] as? T
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ModuleDependencies {
|
interface ModuleDependencies {
|
||||||
val descriptors: List<ModuleDescriptorImpl>
|
val allDependencies: List<ModuleDescriptorImpl>
|
||||||
|
val modulesWhoseInternalsAreVisible: Set<ModuleDescriptorImpl>
|
||||||
}
|
}
|
||||||
|
|
||||||
class ModuleDependenciesImpl(override val descriptors: List<ModuleDescriptorImpl>) : ModuleDependencies
|
class ModuleDependenciesImpl(
|
||||||
|
override val allDependencies: List<ModuleDescriptorImpl>,
|
||||||
|
override val modulesWhoseInternalsAreVisible: Set<ModuleDescriptorImpl>
|
||||||
|
) : ModuleDependencies
|
||||||
|
|
||||||
class LazyModuleDependencies(
|
class LazyModuleDependencies(
|
||||||
storageManager: StorageManager,
|
storageManager: StorageManager,
|
||||||
computeDependencies: () -> List<ModuleDescriptorImpl>
|
computeDependencies: () -> List<ModuleDescriptorImpl>,
|
||||||
|
computeModulesWhoseInternalsAreVisible: () -> Set<ModuleDescriptorImpl>
|
||||||
) : ModuleDependencies {
|
) : ModuleDependencies {
|
||||||
private val dependencies = storageManager.createLazyValue(computeDependencies)
|
private val dependencies = storageManager.createLazyValue(computeDependencies)
|
||||||
|
private val visibleInternals = storageManager.createLazyValue(computeModulesWhoseInternalsAreVisible)
|
||||||
|
|
||||||
override val descriptors: List<ModuleDescriptorImpl>
|
override val allDependencies: List<ModuleDescriptorImpl> get() = dependencies()
|
||||||
get() = dependencies()
|
override val modulesWhoseInternalsAreVisible: Set<ModuleDescriptorImpl> get() = visibleInternals()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ public class ErrorUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFriend(@NotNull ModuleDescriptor other) {
|
public boolean shouldSeeInternalsOf(@NotNull ModuleDescriptor targetModule) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user