Implement ModuleSourceInfo.getDependentModules()

This commit is contained in:
Pavel V. Talanov
2014-09-19 14:45:35 +04:00
parent bf546c83fb
commit 5847c3559b
2 changed files with 136 additions and 4 deletions
@@ -0,0 +1,90 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.plugin.caches.resolve
import com.intellij.openapi.module.Module
import com.intellij.util.containers.MultiMap
import com.intellij.openapi.project.Project
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleOrderEntry
import gnu.trove.THashSet
import com.intellij.util.containers.Queue
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.CachedValueProvider
import com.intellij.openapi.roots.ProjectRootModificationTracker
import java.util.HashSet
//NOTE: this is an approximation that may contain more module infos then the exact solution
public fun ModuleSourceInfo.getDependentModules(): Set<ModuleSourceInfo> {
val dependents = getDependents(module)
if (isTests()) {
return dependents.mapTo(HashSet<ModuleSourceInfo>()) { it.testSourceInfo() }
}
else {
return dependents.flatMapTo(HashSet<ModuleSourceInfo>()) { listOf(it.productionSourceInfo(), it.testSourceInfo()) }
}
}
//NOTE: getDependents adapted from com.intellij.openapi.module.impl.scopes.ModuleWithDependentsScope#buildDependents()
private fun getDependents(module: Module): Set<Module> {
val result = THashSet<Module>()
result.add(module)
val processedExporting = THashSet<Module>()
val index = getModuleIndex(module.getProject())
val walkingQueue = Queue<Module>(10)
walkingQueue.addLast(module)
while (!walkingQueue.isEmpty()) {
val current = walkingQueue.pullFirst()
processedExporting.add(current!!)
result.addAll(index.plainUsages[current])
for (dependent in index.exportingUsages[current]) {
result.add(dependent)
if (processedExporting.add(dependent)) {
walkingQueue.addLast(dependent)
}
}
}
return result
}
private class ModuleIndex {
val plainUsages = MultiMap.create<Module, Module>()
val exportingUsages = MultiMap.create<Module, Module>()
}
private fun getModuleIndex(project: Project): ModuleIndex {
return CachedValuesManager.getManager(project).getCachedValue(project) {
val index = ModuleIndex()
for (module in ModuleManager.getInstance(project).getModules()) {
for (orderEntry in ModuleRootManager.getInstance(module).getOrderEntries()) {
if (orderEntry is ModuleOrderEntry) {
val referenced = orderEntry.getModule()
if (referenced != null) {
val map = if (orderEntry.isExported()) index.exportingUsages else index.plainUsages
map.putValue(referenced, module)
}
}
}
}
CachedValueProvider.Result(index, ProjectRootModificationTracker.getInstance(project))
}!!
}