mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJPL-246737 Use ModuleDependenciesGraph to compute module unloaded dependents
GitOrigin-RevId: 512fbeaab7193361f48b1f136cab920b808e5c9c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
e1526be15a
commit
45af6be781
@@ -22,6 +22,8 @@ import org.jetbrains.annotations.NonNls
|
||||
public interface WorkspaceModelInternal: WorkspaceModel {
|
||||
public val entityStorage: VersionedEntityStorageImpl
|
||||
|
||||
public val unloadedEntitiesStorage: VersionedEntityStorageImpl
|
||||
|
||||
/**
|
||||
* Returns a snapshot of the storage containing unloaded entities.
|
||||
* Unloaded entities must be ignored by almost all code in the IDE, so this property isn't supposed for general use.
|
||||
@@ -112,4 +114,3 @@ public interface WorkspaceModelInternal: WorkspaceModel {
|
||||
@ApiStatus.Experimental
|
||||
public suspend fun awaitSynchronizationWithJpsModel()
|
||||
}
|
||||
|
||||
|
||||
+159
@@ -3,6 +3,9 @@ package com.intellij.workspaceModel.ide.legacyBridge
|
||||
|
||||
import com.intellij.openapi.roots.DependencyScope
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||
import com.intellij.platform.backend.workspace.WorkspaceModel
|
||||
import com.intellij.platform.backend.workspace.impl.WorkspaceModelInternal
|
||||
import com.intellij.platform.workspace.jps.entities.ModuleEntity
|
||||
import com.intellij.projectModel.ModuleDependenciesGraphService
|
||||
import com.intellij.testFramework.junit5.TestApplication
|
||||
import com.intellij.testFramework.rules.ProjectModelExtension
|
||||
@@ -297,4 +300,160 @@ class ModuleDependenciesGraphServiceImplTest {
|
||||
.describedAs("getIn() should return direct dependents even when not exported")
|
||||
.containsExactlyInAnyOrder("module-b", "module-c")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no unloaded modules returns empty`() {
|
||||
val main = projectModel.createModule("main")
|
||||
val mainEntity = main.findModuleEntity()!!
|
||||
|
||||
assertThat(graph.getModuleDependenciesGraph().getModuleUnloadedDependents(mainEntity))
|
||||
.describedAs("With no unloaded modules in the project, the result must be empty")
|
||||
.isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unloaded module directly depending on loaded module`() {
|
||||
// unloaded → main
|
||||
val unloaded = projectModel.createModule("unloaded")
|
||||
val main = projectModel.createModule("main")
|
||||
ModuleRootModificationUtil.addDependency(unloaded, main)
|
||||
|
||||
projectModel.setUnloadedModules("unloaded")
|
||||
|
||||
val mainEntity = main.findModuleEntity()!!
|
||||
assertThat(graph.getModuleDependenciesGraph().getModuleUnloadedDependents(mainEntity).map { it.name })
|
||||
.describedAs("Direct unloaded dependent must be returned")
|
||||
.containsExactlyInAnyOrder("unloaded")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unloaded module reached via exported transitive edge`() {
|
||||
// unloaded → main, main → common (exported)
|
||||
val unloaded = projectModel.createModule("unloaded")
|
||||
val main = projectModel.createModule("main")
|
||||
val common = projectModel.createModule("common")
|
||||
ModuleRootModificationUtil.addDependency(unloaded, main)
|
||||
ModuleRootModificationUtil.addDependency(main, common, DependencyScope.COMPILE, true)
|
||||
|
||||
projectModel.setUnloadedModules("unloaded")
|
||||
|
||||
val commonEntity = common.findModuleEntity()!!
|
||||
assertThat(graph.getModuleDependenciesGraph().getModuleUnloadedDependents(commonEntity).map { it.name })
|
||||
.describedAs("Unloaded module must reach `common` via main's exported edge")
|
||||
.containsExactlyInAnyOrder("unloaded")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `non-exported edge blocks unloaded propagation`() {
|
||||
// unloaded → main, main → util (NOT exported)
|
||||
val unloaded = projectModel.createModule("unloaded")
|
||||
val main = projectModel.createModule("main")
|
||||
val util = projectModel.createModule("util")
|
||||
ModuleRootModificationUtil.addDependency(unloaded, main)
|
||||
ModuleRootModificationUtil.addDependency(main, util, DependencyScope.COMPILE, false)
|
||||
|
||||
projectModel.setUnloadedModules("unloaded")
|
||||
|
||||
val utilEntity = util.findModuleEntity()!!
|
||||
assertThat(graph.getModuleDependenciesGraph().getModuleUnloadedDependents(utilEntity))
|
||||
.describedAs("Non-exported main → util edge must NOT propagate the unloaded dependent")
|
||||
.isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `multiple unloaded modules depending on same loaded module`() {
|
||||
// unloadedA → main, unloadedB → main
|
||||
val unloadedA = projectModel.createModule("unloaded-a")
|
||||
val unloadedB = projectModel.createModule("unloaded-b")
|
||||
val main = projectModel.createModule("main")
|
||||
ModuleRootModificationUtil.addDependency(unloadedA, main)
|
||||
ModuleRootModificationUtil.addDependency(unloadedB, main)
|
||||
|
||||
projectModel.setUnloadedModules("unloaded-a", "unloaded-b")
|
||||
|
||||
val mainEntity = main.findModuleEntity()!!
|
||||
assertThat(graph.getModuleDependenciesGraph().getModuleUnloadedDependents(mainEntity).map { it.name })
|
||||
.describedAs("All unloaded direct dependents must be returned")
|
||||
.containsExactlyInAnyOrder("unloaded-a", "unloaded-b")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `reloading clears unloaded dependents`() {
|
||||
// unloaded → main
|
||||
val unloaded = projectModel.createModule("unloaded")
|
||||
val main = projectModel.createModule("main")
|
||||
ModuleRootModificationUtil.addDependency(unloaded, main)
|
||||
|
||||
projectModel.setUnloadedModules("unloaded")
|
||||
val mainEntityAfterUnload = main.findModuleEntity()!!
|
||||
assertThat(graph.getModuleDependenciesGraph().getModuleUnloadedDependents(mainEntityAfterUnload).map { it.name })
|
||||
.containsExactlyInAnyOrder("unloaded")
|
||||
|
||||
projectModel.setUnloadedModules()
|
||||
val mainEntityAfterReload = main.findModuleEntity()!!
|
||||
assertThat(graph.getModuleDependenciesGraph().getModuleUnloadedDependents(mainEntityAfterReload))
|
||||
.describedAs("After reload, no unloaded dependents should remain")
|
||||
.isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unloaded argument returns empty`() {
|
||||
// unloaded → main
|
||||
val unloaded = projectModel.createModule("unloaded")
|
||||
val main = projectModel.createModule("main")
|
||||
ModuleRootModificationUtil.addDependency(unloaded, main)
|
||||
|
||||
projectModel.setUnloadedModules("unloaded")
|
||||
|
||||
val unloadedEntity = (WorkspaceModel.getInstance(projectModel.project) as WorkspaceModelInternal)
|
||||
.currentSnapshotOfUnloadedEntities
|
||||
.entities(ModuleEntity::class.java)
|
||||
.first { it.name == "unloaded" }
|
||||
assertThat(graph.getModuleDependenciesGraph().getModuleUnloadedDependents(unloadedEntity))
|
||||
.describedAs("Passing an unloaded ModuleEntity is not supported")
|
||||
.isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getModuleDependants is not polluted by unloaded modules`() {
|
||||
// unloaded → main, sibling → main (loaded, exported)
|
||||
val unloaded = projectModel.createModule("unloaded")
|
||||
val main = projectModel.createModule("main")
|
||||
val sibling = projectModel.createModule("sibling")
|
||||
ModuleRootModificationUtil.addDependency(unloaded, main)
|
||||
ModuleRootModificationUtil.addDependency(sibling, main, DependencyScope.COMPILE, true)
|
||||
|
||||
projectModel.setUnloadedModules("unloaded")
|
||||
|
||||
val mainEntity = main.findModuleEntity()!!
|
||||
val depsGraph = graph.getModuleDependenciesGraph()
|
||||
assertThat(depsGraph.getModuleDependants(mainEntity).map { it.name })
|
||||
.describedAs("getModuleDependants must contain only loaded modules")
|
||||
.containsExactlyInAnyOrder("sibling")
|
||||
assertThat(depsGraph.getModuleUnloadedDependents(mainEntity).map { it.name })
|
||||
.containsExactlyInAnyOrder("unloaded")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `cyclic exported loaded graph with unloaded entry does not loop`() {
|
||||
// unloaded → a; a → b (exported); b → a (exported)
|
||||
val unloaded = projectModel.createModule("unloaded")
|
||||
val a = projectModel.createModule("module-a")
|
||||
val b = projectModel.createModule("module-b")
|
||||
ModuleRootModificationUtil.addDependency(unloaded, a)
|
||||
ModuleRootModificationUtil.addDependency(a, b, DependencyScope.COMPILE, true)
|
||||
ModuleRootModificationUtil.addDependency(b, a, DependencyScope.COMPILE, true)
|
||||
|
||||
projectModel.setUnloadedModules("unloaded")
|
||||
|
||||
val aEntity = a.findModuleEntity()!!
|
||||
val bEntity = b.findModuleEntity()!!
|
||||
val depsGraph = graph.getModuleDependenciesGraph()
|
||||
assertThat(depsGraph.getModuleUnloadedDependents(aEntity).map { it.name })
|
||||
.describedAs("Query from `a`: unloaded harvested at `a` (direct dependent)")
|
||||
.containsExactlyInAnyOrder("unloaded")
|
||||
assertThat(depsGraph.getModuleUnloadedDependents(bEntity).map { it.name })
|
||||
.describedAs("Query from `b`: traverses b → a via exported edge")
|
||||
.containsExactlyInAnyOrder("unloaded")
|
||||
}
|
||||
}
|
||||
|
||||
+12
-5
@@ -24,13 +24,20 @@ data class LibraryOrSdkDependencyEdge(
|
||||
val orderNumber: Int,
|
||||
)
|
||||
|
||||
/**
|
||||
* [getModuleDependants] returns [ModuleEntity] which depend on the given module taking into account exported dependencies.
|
||||
*
|
||||
* [getLibraryOrSdkDependants] returns a collection of [LibraryOrSdkDependencyEdge] which contains a dependent on give [SymbolicEntityId] module and its order number.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
interface ModuleDependenciesGraph {
|
||||
/**
|
||||
* Returns [ModuleEntity]s which depend on the given module taking into account exported dependencies.
|
||||
*/
|
||||
fun getModuleDependants(module: ModuleEntity): Collection<ModuleEntity>
|
||||
|
||||
/**
|
||||
* Returns a collection of [LibraryOrSdkDependencyEdge] which contains a dependent on give [SymbolicEntityId] module and its order number.
|
||||
*/
|
||||
fun getLibraryOrSdkDependants(libraryOrSdk: SymbolicEntityId<*>): Collection<LibraryOrSdkDependencyEdge>
|
||||
|
||||
/**
|
||||
* Returns unloaded [ModuleEntity]s that transitively depend on [module].
|
||||
*/
|
||||
fun getModuleUnloadedDependents(module: ModuleEntity): Collection<ModuleEntity>
|
||||
}
|
||||
@@ -49,6 +49,9 @@
|
||||
<registryKey key="ide.workspace.model.relative.paths.to.exclude.automatically"
|
||||
defaultValue=".worktrees;.claude/worktrees" restartRequired="true"
|
||||
description="Semicolon-separated list of relative-paths from project root to automatically exclude from indexing and searching."/>
|
||||
<registryKey key="use.wsm.for.dependent.unloaded.modules" defaultValue="true" restartRequired="true"
|
||||
description="Use workspace model based modules graph for calculating dependent unloaded modules"/>
|
||||
|
||||
<persistentFsConnectionListener implementation="com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexCleaner"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
+16
-1
@@ -8,6 +8,7 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
@@ -15,12 +16,17 @@ import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileMoveEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent;
|
||||
import com.intellij.platform.backend.workspace.WorkspaceModel;
|
||||
import com.intellij.platform.workspace.jps.entities.ModuleEntity;
|
||||
import com.intellij.projectModel.ModuleDependenciesGraphService;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.Query;
|
||||
import com.intellij.util.concurrency.ThreadingAssertions;
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileIndex;
|
||||
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSetWithCustomData;
|
||||
import com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexEx;
|
||||
import com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileInternalInfo;
|
||||
import com.intellij.workspaceModel.ide.legacyBridge.ModuleBridges;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -131,7 +137,16 @@ public final class DirectoryIndexImpl extends DirectoryIndex implements Disposab
|
||||
@Override
|
||||
public @NotNull Set<String> getDependentUnloadedModules(@NotNull Module module) {
|
||||
checkAvailability();
|
||||
return getRootIndex().getDependentUnloadedModules(module);
|
||||
if (Registry.is("use.wsm.for.dependent.unloaded.modules")) {
|
||||
ModuleEntity moduleEntity = ModuleBridges.findModuleEntity(module, WorkspaceModel.getInstance(myProject).getCurrentSnapshot());
|
||||
if (moduleEntity == null) return Collections.emptySet();
|
||||
return ContainerUtil.map2Set(
|
||||
ModuleDependenciesGraphService.getInstance(myProject).getModuleDependenciesGraph().getModuleUnloadedDependents(moduleEntity),
|
||||
m -> m.getName()
|
||||
);
|
||||
} else {
|
||||
return getRootIndex().getDependentUnloadedModules(module);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAvailability() {
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ open class WorkspaceModelImpl : WorkspaceModelInternal {
|
||||
private val reactive = WmReactive(this)
|
||||
|
||||
final override val entityStorage: VersionedEntityStorageImpl
|
||||
private val unloadedEntitiesStorage: VersionedEntityStorageImpl
|
||||
final override val unloadedEntitiesStorage: VersionedEntityStorageImpl
|
||||
private val lock = ThreadContextAwareReentrantLock()
|
||||
|
||||
/** replay = 1 is needed to send the very first state when the subscription fo the flow happens.
|
||||
|
||||
+102
-61
@@ -12,88 +12,129 @@ import com.intellij.platform.workspace.jps.entities.SdkDependency
|
||||
import com.intellij.platform.workspace.storage.CachedValue
|
||||
import com.intellij.platform.workspace.storage.EntityStorage
|
||||
import com.intellij.platform.workspace.storage.SymbolicEntityId
|
||||
import com.intellij.platform.workspace.storage.VersionedEntityStorage
|
||||
import com.intellij.projectModel.LibraryOrSdkDependencyEdge
|
||||
import com.intellij.projectModel.ModuleDependenciesGraph
|
||||
import com.intellij.projectModel.ModuleDependenciesGraphService
|
||||
|
||||
internal class ModuleDependenciesGraphServiceImpl(project: Project): ModuleDependenciesGraphService {
|
||||
|
||||
private val entityStore: VersionedEntityStorage = (WorkspaceModel.getInstance(project) as WorkspaceModelInternal).entityStorage
|
||||
|
||||
fun exportedDependentsGraph(): ModuleDependenciesGraph = entityStore.cachedValue(dependentsGraph)
|
||||
private val workspaceModel: WorkspaceModelInternal = WorkspaceModel.getInstance(project) as WorkspaceModelInternal
|
||||
|
||||
override fun getModuleDependenciesGraph(): ModuleDependenciesGraph {
|
||||
return exportedDependentsGraph()
|
||||
val loaded = workspaceModel.entityStorage.cachedValue(loadedDependentsGraph)
|
||||
val unloaded = workspaceModel.unloadedEntitiesStorage.cachedValue(unloadedDirectDependentsGraph)
|
||||
return CompositeModuleDependenciesGraph(loaded, unloaded)
|
||||
}
|
||||
|
||||
private val dependentsGraph = CachedValue { storage ->
|
||||
buildGraph(storage)
|
||||
}
|
||||
private val loadedDependentsGraph = CachedValue { storage -> buildLoadedDependents(storage) }
|
||||
private val unloadedDirectDependentsGraph = CachedValue { storage -> buildUnloadedDirectDependents(storage) }
|
||||
|
||||
private data class ModuleDependencyEdge(
|
||||
val dependent: ModuleEntity,
|
||||
val exported: Boolean,
|
||||
)
|
||||
|
||||
companion object {
|
||||
fun buildGraph(storage: EntityStorage): ModuleDependenciesGraph {
|
||||
return object : ModuleDependenciesGraph {
|
||||
private val moduleDirectDependents: Map<ModuleId, List<ModuleDependencyEdge>>
|
||||
private val libraryDependents: Map<SymbolicEntityId<*>, List<LibraryOrSdkDependencyEdge>>
|
||||
private class LoadedDependents(
|
||||
val moduleDirectDependents: Map<ModuleId, List<ModuleDependencyEdge>>,
|
||||
val libraryDependents: Map<SymbolicEntityId<*>, List<LibraryOrSdkDependencyEdge>>,
|
||||
)
|
||||
|
||||
init {
|
||||
val dependentsMap = HashMap<ModuleId, MutableList<ModuleDependencyEdge>>()
|
||||
val libraryDependentsMap = HashMap<SymbolicEntityId<*>, MutableList<LibraryOrSdkDependencyEdge>>()
|
||||
private class UnloadedDirectDependents(
|
||||
val moduleDirectDependents: Map<ModuleId, List<ModuleEntity>>,
|
||||
)
|
||||
|
||||
for (module in storage.entities(ModuleEntity::class.java)) {
|
||||
module.dependencies.forEachIndexed { index, dep ->
|
||||
when (dep) {
|
||||
is ModuleDependency -> {
|
||||
dependentsMap
|
||||
.computeIfAbsent(dep.module) { mutableListOf() }
|
||||
.add(ModuleDependencyEdge(module, dep.exported))
|
||||
}
|
||||
is LibraryDependency -> {
|
||||
libraryDependentsMap.computeIfAbsent(dep.library) { mutableListOf() }
|
||||
.add(LibraryOrSdkDependencyEdge(module, index))
|
||||
dep.library
|
||||
}
|
||||
is SdkDependency -> {
|
||||
libraryDependentsMap.computeIfAbsent(dep.sdk) { mutableListOf() }
|
||||
.add(LibraryOrSdkDependencyEdge(module, index))
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
private class CompositeModuleDependenciesGraph(
|
||||
private val loaded: LoadedDependents,
|
||||
private val unloaded: UnloadedDirectDependents,
|
||||
) : ModuleDependenciesGraph {
|
||||
|
||||
override fun getLibraryOrSdkDependants(libraryOrSdk: SymbolicEntityId<*>): Collection<LibraryOrSdkDependencyEdge> {
|
||||
return loaded.libraryDependents[libraryOrSdk] ?: emptyList()
|
||||
}
|
||||
|
||||
override fun getModuleDependants(module: ModuleEntity): Collection<ModuleEntity> {
|
||||
val result = HashSet<ModuleEntity>()
|
||||
val queue = ArrayDeque<ModuleEntity>()
|
||||
queue.add(module)
|
||||
|
||||
while (queue.isNotEmpty()) {
|
||||
val current = queue.removeFirst()
|
||||
val edges = loaded.moduleDirectDependents[current.symbolicId] ?: continue
|
||||
|
||||
for (edge in edges) {
|
||||
if (result.add(edge.dependent) && edge.exported) {
|
||||
queue.add(edge.dependent)
|
||||
}
|
||||
|
||||
this.libraryDependents = libraryDependentsMap
|
||||
this.moduleDirectDependents = dependentsMap
|
||||
}
|
||||
|
||||
override fun getLibraryOrSdkDependants(libraryOrSdk: SymbolicEntityId<*>): Collection<LibraryOrSdkDependencyEdge> {
|
||||
return libraryDependents[libraryOrSdk] ?: emptyList()
|
||||
}
|
||||
|
||||
override fun getModuleDependants(module: ModuleEntity): Collection<ModuleEntity> {
|
||||
val result = HashSet<ModuleEntity>()
|
||||
val queue = ArrayDeque<ModuleEntity>()
|
||||
queue.add(module)
|
||||
|
||||
while (queue.isNotEmpty()) {
|
||||
val current = queue.removeFirst()
|
||||
val edges = moduleDirectDependents[current.symbolicId] ?: emptyList()
|
||||
|
||||
for (edge in edges) {
|
||||
if (result.add(edge.dependent) && edge.exported) {
|
||||
queue.add(edge.dependent)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getModuleUnloadedDependents(module: ModuleEntity): Collection<ModuleEntity> {
|
||||
val result = LinkedHashSet<ModuleEntity>()
|
||||
val visited = HashSet<ModuleEntity>()
|
||||
val queue = ArrayDeque<ModuleEntity>()
|
||||
|
||||
queue.add(module)
|
||||
visited.add(module)
|
||||
while (queue.isNotEmpty()) {
|
||||
val current = queue.removeFirst()
|
||||
unloaded.moduleDirectDependents[current.symbolicId]?.let {
|
||||
result.addAll(it)
|
||||
}
|
||||
|
||||
val edges = loaded.moduleDirectDependents[current.symbolicId] ?: continue
|
||||
for (edge in edges) {
|
||||
if (edge.exported && visited.add(edge.dependent)) {
|
||||
queue.add(edge.dependent)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun buildLoadedDependents(storage: EntityStorage): LoadedDependents {
|
||||
val dependentsMap = HashMap<ModuleId, MutableList<ModuleDependencyEdge>>()
|
||||
val libraryDependentsMap = HashMap<SymbolicEntityId<*>, MutableList<LibraryOrSdkDependencyEdge>>()
|
||||
|
||||
for (module in storage.entities(ModuleEntity::class.java)) {
|
||||
module.dependencies.forEachIndexed { index, dep ->
|
||||
when (dep) {
|
||||
is ModuleDependency -> {
|
||||
dependentsMap
|
||||
.computeIfAbsent(dep.module) { mutableListOf() }
|
||||
.add(ModuleDependencyEdge(module, dep.exported))
|
||||
}
|
||||
is LibraryDependency -> {
|
||||
libraryDependentsMap.computeIfAbsent(dep.library) { mutableListOf() }
|
||||
.add(LibraryOrSdkDependencyEdge(module, index))
|
||||
}
|
||||
is SdkDependency -> {
|
||||
libraryDependentsMap.computeIfAbsent(dep.sdk) { mutableListOf() }
|
||||
.add(LibraryOrSdkDependencyEdge(module, index))
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return LoadedDependents(dependentsMap, libraryDependentsMap)
|
||||
}
|
||||
|
||||
private fun buildUnloadedDirectDependents(storage: EntityStorage): UnloadedDirectDependents {
|
||||
val moduleDirectDependents = HashMap<ModuleId, MutableList<ModuleEntity>>()
|
||||
for (unloadedModule in storage.entities(ModuleEntity::class.java)) {
|
||||
for (dep in unloadedModule.dependencies) {
|
||||
if (dep is ModuleDependency) {
|
||||
moduleDirectDependents
|
||||
.computeIfAbsent(dep.module) { mutableListOf() }
|
||||
.add(unloadedModule)
|
||||
}
|
||||
}
|
||||
}
|
||||
return UnloadedDirectDependents(moduleDirectDependents)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user