void (@NotNull VirtualFile root, @NotNull List<? extends ExternalAnnotation> annotations) { Project project = myPsiManager.getProject(); Map<Optional<VirtualFile>, List<ExternalAnnotation>> annotationsByFiles = annotations.stream() .collect(Collectors.groupingBy(annotation -> Optional.ofNullable(getFileForAnnotations(root, annotation.getOwner(), project)) .map(xmlFile -> xmlFile.getVirtualFile()))); List<VirtualFile> files = StreamEx.ofKeys(annotationsByFiles).flatMap(StreamEx::of).nonNull().toList(); ReadonlyStatusHandler.OperationStatus status = ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(files); if (status.hasReadonlyFiles()) { VirtualFile[] readonlyFiles = status.getReadonlyFiles(); annotationsByFiles.keySet() .removeIf(opt -> opt.filter(f -> ArrayUtil.contains(f, readonlyFiles)).isPresent()); } if (annotationsByFiles.isEmpty()) return; WriteCommandAction.writeCommandAction(project).run(new ThrowableRunnable<>() { @Override public void run() throws RuntimeException { if (project.isDisposed()) return; if (DumbService.isDumb(project)) { DumbService.getInstance(project).runWhenSmart(() -> WriteCommandAction.writeCommandAction(project).run(this)); return; } try { for (Map.Entry<Optional<VirtualFile>, List<ExternalAnnotation>> entry : annotationsByFiles.entrySet()) { VirtualFile annotationsFile = entry.getKey().orElse(null); if (annotationsFile == null) continue; List<ExternalAnnotation> fileAnnotations = entry.getValue(); PsiFile file = PsiManager.getInstance(project).findFile(annotationsFile); if (file instanceof XmlFile) { annotateExternally((XmlFile)file, fileAnnotations); } } UndoManager.getInstance(project).undoableActionPerformed(new BasicUndoableAction() { @Override public void undo() { dropAnnotationsCache(); notifyChangedExternally(); } @Override public void redo() { dropAnnotationsCache(); notifyChangedExternally(); } }); } finally { dropAnnotationsCache(); } } }); }