public static <Node> List<Chunk<Node>> buildChunks(Graph<Node> graph) { final DFSTBuilder<Node> dfstBuilder = new DFSTBuilder<Node>(graph); final TIntArrayList sccs = dfstBuilder.getSCCs(); final List<Chunk<Node>> chunks = new ArrayList<Chunk<Node>>(); sccs.forEach(new TIntProcedure() { int myTNumber = 0; public boolean execute(int size) { Set<Node> packs = new LinkedHashSet<Node>(); for (int j = 0; j < size; j++) { packs.add(dfstBuilder.getNodeByTNumber(myTNumber + j)); } chunks.add(new Chunk<Node>(packs)); myTNumber += size; return true; } }); return chunks; }
/** * Remove cycles in tests included in cycles between production parts */ @NotNull private static List<Chunk<ModuleSourceSet>> filterDuplicates(@NotNull Collection<Chunk<ModuleSourceSet>> sourceSetCycles) { final List<Set<Module>> productionCycles = new ArrayList<Set<Module>>(); for (Chunk<ModuleSourceSet> cycle : sourceSetCycles) { ModuleSourceSet.Type type = getCommonType(cycle); if (type == ModuleSourceSet.Type.PRODUCTION) { productionCycles.add(ModuleSourceSet.getModules(cycle.getNodes())); } } return ContainerUtil.filter(sourceSetCycles, new Condition<Chunk<ModuleSourceSet>>() { @Override public boolean value(Chunk<ModuleSourceSet> chunk) { if (getCommonType(chunk) != ModuleSourceSet.Type.TEST) return true; for (Set<Module> productionCycle : productionCycles) { if (productionCycle.containsAll(ModuleSourceSet.getModules(chunk.getNodes()))) return false; } return true; } }); }
public static List<Chunk<ModuleSourceSet>> getCyclicDependencies(@NotNull Project project, @NotNull List<Module> modules) { Graph<ModuleSourceSet> graph = createModuleSourceDependenciesGraph(new DefaultModulesProvider(project)); Collection<Chunk<ModuleSourceSet>> chunks = GraphAlgorithms.getInstance().computeStronglyConnectedComponents(graph); final Set<Module> modulesSet = new HashSet<Module>(modules); return ContainerUtil.filter(chunks, new Condition<Chunk<ModuleSourceSet>>() { @Override public boolean value(Chunk<ModuleSourceSet> chunk) { for (ModuleSourceSet sourceSet : chunk.getNodes()) { if (modulesSet.contains(sourceSet.getModule())) { return true; } } return false; } }); }
public void testGraph2() { final Map<String, String> arcs = new HashMap<String, String>(); arcs.put("a", "b"); arcs.put("b", "ac"); arcs.put("c", "ad"); arcs.put("d", ""); final Graph<Chunk<String>> graph = getAlgorithmsInstance().computeSCCGraph(initGraph(arcs)); final List<Chunk<String>> expectedNodes = new ArrayList<Chunk<String>>(); Chunk<String> ABC = new Chunk<String>(toSet("a", "b", "c")); expectedNodes.add(ABC); Chunk<String> D = new Chunk<String>("d"); expectedNodes.add(D); checkVertices(expectedNodes, graph.getNodes().iterator()); final Map<Chunk<String>, Set<Chunk<String>>> expectedArcs = new HashMap<Chunk<String>, Set<Chunk<String>>>(); expectedArcs.put(ABC, toSet()); expectedArcs.put(D, toSet(ABC)); checkArcs(expectedArcs, graph); }
private static List<VirtualFile> getFilesInScope(final CompileContextEx context, final Chunk<Module> chunk, final Collection<VirtualFile> files) { final List<VirtualFile> filesInScope = new ArrayList<VirtualFile>(files.size()); ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { for (VirtualFile file : files) { if (context.getCompileScope().belongs(file.getUrl())) { final Module module = context.getModuleByFile(file); if (chunk.getNodes().contains(module)) { filesInScope.add(file); } } } } }); return filesInScope; }
public BackendCompilerWrapper(Chunk<Module> chunk, @NotNull final Project project, @NotNull List<VirtualFile> filesToCompile, @NotNull CompileContextEx compileContext, @NotNull BackendCompiler compiler, TranslatingCompiler.OutputSink sink) { myChunk = chunk; myProject = project; myCompiler = compiler; myCompileContext = compileContext; myFilesToCompile = filesToCompile; mySink = sink; myProjectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); CompileStatistics stat = compileContext.getUserData(CompileStatistics.KEY); if (stat == null) { stat = new CompileStatistics(); compileContext.putUserData(CompileStatistics.KEY, stat); } myStatistics = stat; }
@Override public void sort(Chunk<Module> moduleChunk, @NotNull Compiler[] compilers, Class<? extends Compiler> aClass) { if(aClass == TranslatingCompiler.class) { boolean needSwap = false; for(Module module : moduleChunk.getNodes()) { if(ModuleUtilCore.getExtension(module, IkvmModuleExtension.class) != null) { needSwap = true; break; } } if(needSwap) { int javaIndex = indexOfViaInstanceOf(compilers, JavaCompiler.class); int dotNetIndex = indexOfViaInstanceOf(compilers, DotNetCompiler.class); if(javaIndex > dotNetIndex) { ArrayUtil.swap(compilers, javaIndex, dotNetIndex); } } } }
private static List<VirtualFile> getFilesInScope(final CompileContextEx context, final Chunk<Module> chunk, final Collection<VirtualFile> files) { final List<VirtualFile> filesInScope = new ArrayList<>(files.size()); ApplicationManager.getApplication().runReadAction(() -> { for (VirtualFile file : files) { if (context.getCompileScope().belongs(file.getUrl())) { final Module module = context.getModuleByFile(file); if (chunk.getNodes().contains(module)) { filesInScope.add(file); } } } }); return filesInScope; }
private static void recalculateChunkToFilesMap(CompileContextEx context, List<Chunk<Module>> allChunks, VirtualFile[] snapshot, Map<Chunk<Module>, Collection<VirtualFile>> chunkMap) { final Map<Module, List<VirtualFile>> moduleToFilesMap = CompilerUtil.buildModuleToFilesMap(context, snapshot); for (Chunk<Module> moduleChunk : allChunks) { List<VirtualFile> files = Collections.emptyList(); for (Module module : moduleChunk.getNodes()) { final List<VirtualFile> moduleFiles = moduleToFilesMap.get(module); if (moduleFiles != null) { files = ContainerUtil.concat(files, moduleFiles); } } chunkMap.put(moduleChunk, files); } }
public BackendCompilerWrapper(TranslatingCompiler translatingCompiler, Chunk<Module> chunk, @NotNull final Project project, @NotNull List<VirtualFile> filesToCompile, @NotNull CompileContextEx compileContext, @NotNull BackendCompiler compiler, TranslatingCompiler.OutputSink sink) { myTranslatingCompiler = translatingCompiler; myChunk = chunk; myProject = project; myCompiler = compiler; myCompileContext = compileContext; myFilesToCompile = filesToCompile; mySink = sink; myProjectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); CompileStatistics stat = compileContext.getUserData(CompileStatistics.KEY); if(stat == null) { stat = new CompileStatistics(); compileContext.putUserData(CompileStatistics.KEY, stat); } myStatistics = stat; }
private List<Chunk<ModuleSourceSet>> removeDummyNodes(List<Chunk<ModuleSourceSet>> chunks) { List<Chunk<ModuleSourceSet>> result = new ArrayList<Chunk<ModuleSourceSet>>(chunks.size()); for (Chunk<ModuleSourceSet> chunk : chunks) { Set<ModuleSourceSet> nodes = new LinkedHashSet<ModuleSourceSet>(); for (ModuleSourceSet sourceSet : chunk.getNodes()) { if (!isDummy(sourceSet)) { nodes.add(sourceSet); } } result.add(new Chunk<ModuleSourceSet>(nodes)); } return result; }
private static List<Chunk<ModuleSourceSet>> removeSingleElementChunks(Collection<Chunk<ModuleSourceSet>> chunks) { return ContainerUtil.filter(chunks, new Condition<Chunk<ModuleSourceSet>>() { @Override public boolean value(Chunk<ModuleSourceSet> chunk) { return chunk.getNodes().size() > 1; } }); }
@Nullable private static ModuleSourceSet.Type getCommonType(@NotNull Chunk<ModuleSourceSet> cycle) { ModuleSourceSet.Type type = null; for (ModuleSourceSet set : cycle.getNodes()) { if (type == null) { type = set.getType(); } else if (type != set.getType()) { return null; } } return type; }
@Nullable public static Charset getPreferredModuleEncoding(Chunk<Module> chunk) { CompilerEncodingService service = null; for (Module module : chunk.getNodes()) { if (service == null) { service = getInstance(module.getProject()); } final Charset charset = service.getPreferredModuleEncoding(module); if (charset != null) { return charset; } } return null; }
public static List<Chunk<Module>> getSortedModuleChunks(Project project, List<Module> modules) { final Module[] allModules = ModuleManager.getInstance(project).getModules(); final List<Chunk<Module>> chunks = getSortedChunks(createModuleGraph(allModules)); final Set<Module> modulesSet = new HashSet<Module>(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 (!ContainerUtil.intersects(chunk.getNodes(), modulesSet)) { it.remove(); } } return chunks; }
public static <Node> List<Chunk<Node>> getSortedChunks(final Graph<Node> graph) { final Graph<Chunk<Node>> chunkGraph = toChunkGraph(graph); final List<Chunk<Node>> chunks = new ArrayList<Chunk<Node>>(chunkGraph.getNodes().size()); for (final Chunk<Node> chunk : chunkGraph.getNodes()) { chunks.add(chunk); } DFSTBuilder<Chunk<Node>> builder = new DFSTBuilder<Chunk<Node>>(chunkGraph); if (!builder.isAcyclic()) { LOG.error("Acyclic graph expected"); return null; } Collections.sort(chunks, builder.comparator()); return chunks; }
private List<Chunk<Module>> getCycleChunks() { List<Chunk<Module>> chunks = ModuleCompilerUtil.getSortedModuleChunks(myProject, Arrays.asList(ModuleManager.getInstance(myProject).getModules())); for (Iterator<Chunk<Module>> it = chunks.iterator(); it.hasNext();) { final Chunk<Module> chunk = it.next(); if (chunk.getNodes().size() == 1) { it.remove(); } } return chunks; }
private void initChunksPanel() { List<Chunk<Module>> chunks = getCycleChunks(); if (chunks.isEmpty()) { return; } myChunksPanel.setLayout(new BorderLayout()); myChunksPanel.setBorder( IdeBorderFactory.createTitledBorder(CompilerBundle.message("generate.ant.build.dialog.cyclic.modules.table.title"), true)); JLabel textLabel = new JLabel(CompilerBundle.message("generate.ant.build.dialog.cyclic.modules.table.description")); textLabel.setUI(new MultiLineLabelUI()); textLabel.setBorder(IdeBorderFactory.createEmptyBorder(4, 4, 6, 4)); myChunksPanel.add(textLabel, BorderLayout.NORTH); myTableModel = new MyTableModel(chunks); myTable = new Table(myTableModel); final MyTableCellRenderer cellRenderer = new MyTableCellRenderer(); final TableColumn nameColumn = myTable.getColumnModel().getColumn(MyTableModel.NAME_COLUMN); nameColumn.setCellEditor(ComboBoxTableCellEditor.INSTANCE); nameColumn.setCellRenderer(cellRenderer); final TableColumn labelColumn = myTable.getColumnModel().getColumn(MyTableModel.NUMBER_COLUMN); labelColumn.setCellRenderer(cellRenderer); final Dimension preferredSize = new Dimension(myTable.getPreferredSize()); preferredSize.height = (myTableModel.getRowCount() + 2) * myTable.getRowHeight() + myTable.getTableHeader().getHeight(); final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable); scrollPane.setPreferredSize(preferredSize); myChunksPanel.add(scrollPane, BorderLayout.CENTER); }
private MyTableModel(List<Chunk<Module>> chunks) { for (final Chunk<Module> chunk : chunks) { final ListWithSelection<String> item = new ListWithSelection<String>(); for (final Module module : chunk.getNodes()) { item.add(module.getName()); } item.selectFirst(); myItems.add(new Pair<String, ListWithSelection>(createCycleName(chunk), item)); } }
private static String createCycleName(Chunk<Module> chunk) { final StringBuilder buf = new StringBuilder(); for (Module module : chunk.getNodes()) { if (buf.length() > 0) { buf.append(", "); } buf.append(module.getName()); } buf.insert(0, "["); buf.append("]"); return buf.toString(); }
public void testGraph1() { final Map<String, String> arcs = new HashMap<String, String>(); arcs.put("a", "b"); arcs.put("b", "c"); arcs.put("c", "bd"); arcs.put("d", "e"); arcs.put("e", "d"); final Graph<Chunk<String>> graph = getAlgorithmsInstance().computeSCCGraph(initGraph(arcs)); final List<Chunk<String>> expectedNodes = new ArrayList<Chunk<String>>(); Chunk<String> A = new Chunk<String>("a"); expectedNodes.add(A); Chunk<String> BC = new Chunk<String>(toSet("b", "c")); expectedNodes.add(BC); Chunk<String> DE = new Chunk<String>(toSet("d", "e")); expectedNodes.add(DE); checkVertices(expectedNodes, graph.getNodes().iterator()); final Map<Chunk<String>, Set<Chunk<String>>> expectedArcs = new HashMap<Chunk<String>, Set<Chunk<String>>>(); expectedArcs.put(A, toSet()); expectedArcs.put(BC, toSet(A)); expectedArcs.put(DE, toSet(BC)); checkArcs(expectedArcs, graph); }
private static void checkArcs(Map<Chunk<String>, Set<Chunk<String>>> expectedArcs, Graph<Chunk<String>> graph) { for (Chunk<String> chunk : graph.getNodes()) { final List<Chunk<String>> ins = new ArrayList<Chunk<String>>(); final Iterator<Chunk<String>> insIterator = graph.getIn(chunk); while (insIterator.hasNext()) { ins.add(insIterator.next()); } final Set<Chunk<String>> expectedIns = expectedArcs.get(chunk); assertTrue(expectedIns.size() == ins.size()); assertTrue(expectedIns.equals(new HashSet<Chunk<String>>(ins))); } }
private static void checkVertices(List<Chunk<String>> expected, Iterator<Chunk<String>> nodes) { List<Chunk<String>> realNodes = new ArrayList<Chunk<String>>(); while (nodes.hasNext()) { realNodes.add(nodes.next()); } assertTrue(expected.size() == realNodes.size()); assertTrue(new HashSet<Chunk<String>>(expected).equals(new HashSet<Chunk<String>>(realNodes))); }
@Override public void check(ProjectStructureProblemsHolder problemsHolder) { final Graph<Chunk<ModuleRootModel>> graph = ModuleCompilerUtil.toChunkGraph(myContext.getModulesConfigurator().createGraphGenerator()); final Collection<Chunk<ModuleRootModel>> chunks = graph.getNodes(); List<String> cycles = new ArrayList<String>(); for (Chunk<ModuleRootModel> chunk : chunks) { final Set<ModuleRootModel> modules = chunk.getNodes(); List<String> names = new ArrayList<String>(); for (ModuleRootModel model : modules) { names.add(model.getModule().getName()); } if (modules.size() > 1) { cycles.add(StringUtil.join(names, ", ")); } } if (!cycles.isEmpty()) { final Project project = myContext.getProject(); final PlaceInProjectStructureBase place = new PlaceInProjectStructureBase(project, ProjectStructureConfigurable.getInstance(project).createModulesPlace(), this); final String message; final String description; if (cycles.size() > 1) { message = "Circular dependencies"; @NonNls final String br = "<br> "; StringBuilder cyclesString = new StringBuilder(); for (int i = 0; i < cycles.size(); i++) { cyclesString.append(br).append(i + 1).append(". ").append(cycles.get(i)); } description = ProjectBundle.message("module.circular.dependency.warning.description", cyclesString); } else { message = ProjectBundle.message("module.circular.dependency.warning.short", cycles.get(0)); description = null; } problemsHolder.registerProblem(new ProjectStructureProblemDescription(message, description, place, ProjectStructureProblemType.warning("module-circular-dependency"), Collections.<ConfigurationErrorQuickFix>emptyList())); } }
public void addTranslatingCompiler(@NotNull final TranslatingCompiler compiler, final Set<FileType> inputTypes, final Set<FileType> outputTypes) { myTranslators.add(compiler); myCompilerToInputTypes.put(compiler, inputTypes); myCompilerToOutputTypes.put(compiler, outputTypes); final List<Chunk<Compiler>> chunks = ModuleCompilerUtil.getSortedChunks(createCompilerGraph((List<Compiler>)(List)myTranslators)); myTranslators.clear(); for (Chunk<Compiler> chunk : chunks) { for (Compiler chunkCompiler : chunk.getNodes()) { myTranslators.add((TranslatingCompiler)chunkCompiler); } } }
public Collection<String> getOptions(Chunk<Module> chunk) { final Collection<String> options = super.getOptions(chunk); if(getOptions().GENERATE_IIOP_STUBS) { options.add("-iiop"); } return options; }
public ModuleChunk(CompileContextEx context, Chunk<Module> chunk, Map<Module, List<VirtualFile>> moduleToFilesMap) { super(chunk.getNodes()); myContext = context; for (final Module module : chunk.getNodes()) { final List<VirtualFile> files = moduleToFilesMap.get(module); // Important!!! Collections in the myModuleToFilesMap must be modifiable copies of the corresponding collections // from the moduleToFilesMap. This is needed to support SourceTransforming compilers myModuleToFilesMap.put(module, files == null ? Collections.<VirtualFile>emptyList() : new ArrayList<VirtualFile>(files)); } }
@Override public Collection<String> getOptions(Chunk<Module> chunk) { final Collection<String> options = super.getOptions(chunk); if (getOptions().PROCEED_ON_ERROR) { options.add("-proceedOnError"); } return options; }