boolean (@NotNull Project project, @NotNull Collection<? extends PsiElement> recursive, @NotNull Collection<? extends PsiElement> flat, @NotNull String messagePrefix, boolean notifyOnFail) { Collection<VirtualFile> readonly = new HashSet<>(); // not writable, but could be checked out Collection<VirtualFile> failed = new HashSet<>(); // those located in read-only filesystem boolean seenNonWritablePsiFilesWithoutVirtualFile = ProgressManager.getInstance() .runProcessWithProgressSynchronously(() -> ReadAction.compute(() -> checkReadOnlyStatus(flat, false, readonly, failed) || checkReadOnlyStatus(recursive, true, readonly, failed)), RefactoringBundle.message("progress.title.collect.read.only.files"), false, project); ReadonlyStatusHandler.OperationStatus status = ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(readonly); ContainerUtil.addAll(failed, status.getReadonlyFiles()); if (notifyOnFail && (!failed.isEmpty() || seenNonWritablePsiFilesWithoutVirtualFile && readonly.isEmpty())) { @NlsSafe StringBuilder message = new StringBuilder(messagePrefix).append('\n'); int i = 0; for (VirtualFile virtualFile : failed) { String subj = RefactoringBundle.message(virtualFile.isDirectory() ? "directory.description" : "file.description", virtualFile.getPresentableUrl()); if (virtualFile.getFileSystem().isReadOnly()) { message.append(RefactoringBundle.message("0.is.located.in.a.jar.file", subj)).append('\n'); } else { message.append(RefactoringBundle.message("0.is.read.only", subj)).append('\n'); } if (i++ > 20) { message.append("...\n"); break; } } showErrorMessage(RefactoringBundle.message("error.title"), message.toString(), null, project); return false; } return failed.isEmpty(); }