Couple<Module> (@NotNull Module currentModule, @NotNull Module toDependOn) { assert currentModule != toDependOn; // whatsa lotsa of @&#^%$ codes-a! final Map<Module, ModifiableRootModel> models = new LinkedHashMap<>(); Project project = currentModule.getProject(); for (Module module : ModuleManager.getInstance(project).getModules()) { ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); models.put(module, model); } ModifiableRootModel currentModel = models.get(currentModule); ModifiableRootModel toDependOnModel = models.get(toDependOn); Collection<Chunk<ModifiableRootModel>> nodesBefore = buildChunks(models); for (Chunk<ModifiableRootModel> chunk : nodesBefore) { if (chunk.containsNode(toDependOnModel) && chunk.containsNode(currentModel)) return null; // they circular already } try { currentModel.addModuleOrderEntry(toDependOn); Collection<Chunk<ModifiableRootModel>> nodesAfter = buildChunks(models); for (Chunk<ModifiableRootModel> chunk : nodesAfter) { if (chunk.containsNode(toDependOnModel) && chunk.containsNode(currentModel)) { List<ModifiableRootModel> nodes = ContainerUtil.sorted(ContainerUtil.collect(chunk.getNodes().iterator()), // graph algorithms collections are inherently unstable, so sort to return always the same modules to avoid blinking tests Comparator.comparing(m -> m.getModule().getName())); return Couple.of(nodes.get(0).getModule(), nodes.get(1).getModule()); } } } finally { for (ModifiableRootModel model : models.values()) { model.dispose(); } } return null; }