List<PsiElement> (List<? extends Pair<String, JpsModuleSourceRootType<?>>> toCreate, CreateGroupHandler validator) { List<PsiElement> createdDirectories = new ArrayList<>(toCreate.size()); // first, check that we can create all requested directories if (!ContainerUtil.all(toCreate, dir -> !dir.first.isEmpty() && validator.checkInput(dir.first))) return null; List<Pair<PsiFileSystemItem, JpsModuleSourceRootType<?>>> toMarkAsRoots = new ArrayList<>(toCreate.size()); // now create directories one by one for (Pair<String, JpsModuleSourceRootType<?>> dir : toCreate) { // this call creates a directory if (!validator.canClose(dir.first)) return null; PsiFileSystemItem element = validator.getCreatedElement(); if (element == null) continue; createdDirectories.add(element); // collect folders to mark as source folders later JpsModuleSourceRootType<?> rootType = dir.second; if (rootType != null) { toMarkAsRoots.add(Pair.create(element, rootType)); } } if (!toMarkAsRoots.isEmpty()) { Project project = toMarkAsRoots.get(0).first.getProject(); ProjectFileIndex index = ProjectFileIndex.getInstance(project); WriteAction.run(() -> ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(() -> { for (Pair<PsiFileSystemItem, JpsModuleSourceRootType<?>> each : toMarkAsRoots) { VirtualFile file = each.first.getVirtualFile(); JpsModuleSourceRootType<?> rootType = each.second; // make sure we have a content root for this directory and it's not yet registered as source folder Module module = index.getModuleForFile(file); if (module == null || index.getContentRootForFile(file) == null || index.isInSourceContent(file)) { continue; } ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); ContentEntry entry = MarkRootActionBase.findContentEntry(model, file); if (entry != null) { entry.addSourceFolder(file, rootType); model.commit(); } else { model.dispose(); } } })); } return createdDirectories; }