mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
229 lines
8.3 KiB
Java
229 lines
8.3 KiB
Java
package com.intellij.compiler;
|
|
|
|
import com.intellij.j2ee.j2eeDom.J2EEModuleProperties;
|
|
import com.intellij.j2ee.j2eeDom.application.J2EEApplicationModel;
|
|
import com.intellij.j2ee.j2eeDom.application.ModuleInApplication;
|
|
import com.intellij.j2ee.j2eeDom.xmlData.ObjectsList;
|
|
import com.intellij.openapi.application.Application;
|
|
import com.intellij.openapi.application.ApplicationManager;
|
|
import com.intellij.openapi.diagnostic.Logger;
|
|
import com.intellij.openapi.module.Module;
|
|
import com.intellij.openapi.module.ModuleManager;
|
|
import com.intellij.openapi.module.ModuleType;
|
|
import com.intellij.openapi.project.Project;
|
|
import com.intellij.openapi.roots.ModuleRootManager;
|
|
import com.intellij.util.graph.CachingSemiGraph;
|
|
import com.intellij.util.graph.DFSTBuilder;
|
|
import com.intellij.util.graph.Graph;
|
|
import com.intellij.util.graph.GraphGenerator;
|
|
|
|
import java.util.*;
|
|
|
|
/**
|
|
* @author dsl
|
|
*/
|
|
public final class ModuleCompilerUtil {
|
|
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.ModuleCompilerUtil");
|
|
private ModuleCompilerUtil() { }
|
|
|
|
public static Module[] getDependencies(Module module) {
|
|
if (!ModuleType.J2EE_APPLICATION.equals(module.getModuleType())) {
|
|
return ModuleRootManager.getInstance(module).getDependencies();
|
|
}
|
|
List<Module> result = new ArrayList<Module>();
|
|
final ObjectsList<ModuleInApplication> modules = ((J2EEApplicationModel)J2EEModuleProperties.getInstance(module)).getModules();
|
|
final Iterator<ModuleInApplication> iterator = modules.iterator();
|
|
while (iterator.hasNext()) {
|
|
final ModuleInApplication moduleInApplication = iterator.next();
|
|
final Module depModule = moduleInApplication.getReferenceModule();
|
|
if (depModule != null && !dependsOn(depModule, module)) {
|
|
result.add(depModule);
|
|
}
|
|
}
|
|
return result.toArray(new Module[result.size()]);
|
|
}
|
|
|
|
public static Comparator<Module> moduleDependencyComparator(Project project) {
|
|
final Module[] modules = ModuleManager.getInstance(project).getModules();
|
|
final Graph<Module> graph = createModuleGraph(modules);
|
|
DFSTBuilder<Module> builder = new DFSTBuilder<Module>(graph);
|
|
return builder.comparator();
|
|
}
|
|
|
|
public static Graph<Module> createModuleGraph(final Module[] modules) {
|
|
return GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<Module>() {
|
|
public Collection<Module> getNodes() {
|
|
return Arrays.asList(modules);
|
|
}
|
|
|
|
public Iterator<Module> getIn(Module module) {
|
|
return Arrays.asList(getDependencies(module)).iterator();
|
|
}
|
|
}));
|
|
}
|
|
|
|
private static boolean dependsOn(Module dependant, Module dependee) {
|
|
if (dependant.equals(dependee)) return true;
|
|
final Module[] dependencies = ModuleRootManager.getInstance(dependant).getDependencies();
|
|
for (int i = 0; i < dependencies.length; i++) {
|
|
final Module dependency = dependencies[i];
|
|
if (dependsOn(dependency, dependee)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
public static List<Chunk<Module>> getSortedModuleChunks(Project project, Module[] modules) {
|
|
final Module[] allModules = ModuleManager.getInstance(project).getModules();
|
|
return getSortedModuleChunks(modules, createModuleGraph(allModules));
|
|
}
|
|
|
|
public static List<Chunk<Module>> getSortedModuleChunks(Module[] modules, Graph<Module> moduleGraph) {
|
|
final Graph<Chunk<Module>> graph = toChunkGraph(moduleGraph);
|
|
final List<Chunk<Module>> chunks = new ArrayList<Chunk<Module>>(moduleGraph.getNodes().size());
|
|
for (Iterator<Chunk<Module>> it = graph.getNodes().iterator(); it.hasNext();) {
|
|
chunks.add(it.next());
|
|
}
|
|
DFSTBuilder<Chunk<Module>> builder = new DFSTBuilder<Chunk<Module>>(graph);
|
|
if (!builder.isAcyclic()) {
|
|
LOG.error("Acyclic graph expected");
|
|
return null;
|
|
}
|
|
|
|
Collections.sort(chunks, builder.comparator());
|
|
|
|
if (LOG.isDebugEnabled()) {
|
|
LOG.debug("---Sorted module chunks:");
|
|
logChunks(chunks);
|
|
}
|
|
|
|
final Set<Module> modulesSet = new HashSet<Module>(Arrays.asList(modules));
|
|
// leave only those chunks that contain at least one module from modules
|
|
for (Iterator<Chunk<Module>> it = chunks.iterator(); it.hasNext();) {
|
|
final Chunk<Module> chunk = it.next();
|
|
if (!intersects(chunk.getNodes(), modulesSet)) {
|
|
it.remove();
|
|
}
|
|
}
|
|
if (LOG.isDebugEnabled()) {
|
|
LOG.debug("---Chunks to be processed:");
|
|
logChunks(chunks);
|
|
}
|
|
return chunks;
|
|
}
|
|
|
|
private static void logChunks(final List<Chunk<Module>> chunks) {
|
|
for (Iterator it = chunks.iterator(); it.hasNext();) {
|
|
final Chunk<Module> chunk = (Chunk<Module>)it.next();
|
|
System.out.println(chunk);
|
|
}
|
|
System.out.println("---");
|
|
}
|
|
|
|
private static boolean intersects(Set set1, Set set2) {
|
|
for (Iterator it = set1.iterator(); it.hasNext();) {
|
|
if (set2.contains(it.next())) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static <Node> Graph<Chunk<Node>> toChunkGraph(final Graph<Node> graph) {
|
|
final Set<Chunk<Node>> chunks = new HashSet<Chunk<Node>>();
|
|
|
|
final Map<Node, Chunk<Node>> nodeToChunkMap = new HashMap<Node, Chunk<Node>>();
|
|
for (Iterator<Node> it = graph.getNodes().iterator(); it.hasNext();) {
|
|
final Chunk<Node> chunk = buildChunk(graph, it.next());
|
|
chunks.add(chunk);
|
|
for (Iterator<Node> nodeIterator = chunk.getNodes().iterator(); nodeIterator.hasNext();) {
|
|
nodeToChunkMap.put(nodeIterator.next(), chunk);
|
|
}
|
|
}
|
|
|
|
return GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<Chunk<Node>>() {
|
|
public Collection<Chunk<Node>> getNodes() {
|
|
return chunks;
|
|
}
|
|
|
|
public Iterator<Chunk<Node>> getIn(Chunk<Node> chunk) {
|
|
final Set<Node> chunkNodes = chunk.getNodes();
|
|
final Set<Chunk<Node>> ins = new HashSet<Chunk<Node>>();
|
|
for (Iterator<Node> chunkNodesIterator = chunkNodes.iterator(); chunkNodesIterator.hasNext();) {
|
|
final Node node = chunkNodesIterator.next();
|
|
for (Iterator<Node> nodeIns = graph.getIn(node); nodeIns.hasNext();) {
|
|
final Node in = nodeIns.next();
|
|
if (!chunk.containsNode(in)) {
|
|
ins.add(nodeToChunkMap.get(in));
|
|
}
|
|
}
|
|
}
|
|
return ins.iterator();
|
|
}
|
|
}));
|
|
|
|
}
|
|
|
|
private static <Node> Chunk<Node> buildChunk(Graph<Node> graph, final Node node) {
|
|
final Set<Node> outs = new HashSet<Node>();
|
|
final Set<Node> ins = new HashSet<Node>();
|
|
|
|
addAllReachable(graph, outs, node, true); // add all vertices reachable from node
|
|
addAllReachable(graph, ins, node, false); // add all vertices node is reachable from
|
|
|
|
outs.retainAll(ins);
|
|
if (outs.isEmpty()) {
|
|
return new Chunk<Node>(node);
|
|
}
|
|
|
|
return new Chunk<Node>(outs);
|
|
}
|
|
|
|
private static <Node> void addAllReachable(Graph<Node> graph, final Set<Node> reachableSet, final Node node, final boolean fromTheNode) {
|
|
final Set<Node> toProcess = new HashSet<Node>();
|
|
final Set<Node> alreadyProcessed = new HashSet<Node>();
|
|
toProcess.add(node);
|
|
while (!toProcess.isEmpty()) {
|
|
alreadyProcessed.addAll(toProcess);
|
|
final List<Node> nodes = new ArrayList<Node>(toProcess);
|
|
toProcess.clear();
|
|
for (Iterator<Node> nodesToProcessIterator = nodes.iterator(); nodesToProcessIterator.hasNext();) {
|
|
final Node n = nodesToProcessIterator.next();
|
|
for (Iterator<Node> it = graph.getNodes().iterator(); it.hasNext();) {
|
|
final Node n1 = it.next();
|
|
if (fromTheNode? hasArc(graph, n, n1) : hasArc(graph, n1, n)) {
|
|
reachableSet.add(n1);
|
|
if (!alreadyProcessed.contains(n1)) {
|
|
toProcess.add(n1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static <Node> boolean hasArc(Graph<Node> graph, Node from, Node to) {
|
|
for (Iterator<Node> it = graph.getOut(from); it.hasNext();) {
|
|
if (to.equals(it.next())) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
public static void sortModules(final Project project, final List<Module> modules) {
|
|
final Application applicationEx = ApplicationManager.getApplication();
|
|
if (applicationEx.isDispatchThread()) {
|
|
Collections.sort(modules, moduleDependencyComparator(project));
|
|
}
|
|
else {
|
|
applicationEx.runReadAction(new Runnable() {
|
|
public void run() {
|
|
Collections.sort(modules, moduleDependencyComparator(project));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|