@Override
  public void saveAllDocuments() {
    ApplicationManager.getApplication().assertIsDispatchThread();

    myMultiCaster.beforeAllDocumentsSaving();
    if (myUnsavedDocuments.isEmpty()) return;

    final Map<Document, IOException> failedToSave = new HashMap<Document, IOException>();
    final Set<Document> vetoed = new HashSet<Document>();
    while (true) {
      int count = 0;

      for (Document document : myUnsavedDocuments) {
        if (failedToSave.containsKey(document)) continue;
        if (vetoed.contains(document)) continue;
        try {
          doSaveDocument(document);
        } catch (IOException e) {
          //noinspection ThrowableResultOfMethodCallIgnored
          failedToSave.put(document, e);
        } catch (SaveVetoException e) {
          vetoed.add(document);
        }
        count++;
      }

      if (count == 0) break;
    }

    if (!failedToSave.isEmpty()) {
      handleErrorsOnSave(failedToSave);
    }
  }
 @TestOnly
 public void dropAllUnsavedDocuments() {
   if (!ApplicationManager.getApplication().isUnitTestMode()) {
     throw new RuntimeException("This method is only for test mode!");
   }
   ApplicationManager.getApplication().assertWriteAccessAllowed();
   if (!myUnsavedDocuments.isEmpty()) {
     myUnsavedDocuments.clear();
     fireUnsavedDocumentsDropped();
   }
 }
 @Override
 public boolean canCloseProject(Project project) {
   if (!myUnsavedDocuments.isEmpty()) {
     myOnClose = true;
     try {
       saveAllDocuments();
     } finally {
       myOnClose = false;
     }
   }
   return myUnsavedDocuments.isEmpty();
 }
  private void doSaveDocument(@NotNull final Document document)
      throws IOException, SaveVetoException {
    VirtualFile file = getFile(document);

    if (file == null
        || file instanceof LightVirtualFile
        || file.isValid() && !isFileModified(file)) {
      removeFromUnsaved(document);
      return;
    }

    if (file.isValid() && needsRefresh(file)) {
      file.refresh(false, false);
      if (!myUnsavedDocuments.contains(document)) return;
    }

    for (FileDocumentSynchronizationVetoer vetoer :
        Extensions.getExtensions(FileDocumentSynchronizationVetoer.EP_NAME)) {
      if (!vetoer.maySaveDocument(document)) {
        throw new SaveVetoException();
      }
    }

    final AccessToken token =
        ApplicationManager.getApplication().acquireWriteActionLock(getClass());
    try {
      doSaveDocumentInWriteAction(document, file);
    } finally {
      token.finish();
    }
  }
 private void updateDocumentFromPropertyValue(
     final String value, final Document document, final PropertiesFile propertiesFile) {
   @NonNls String text = value;
   if (myBackSlashPressed.contains(propertiesFile)) {
     text += "\\";
   }
   document.replaceString(0, document.getTextLength(), text);
 }
  @Override
  @NotNull
  public Document[] getUnsavedDocuments() {
    if (myUnsavedDocuments.isEmpty()) {
      return Document.EMPTY_ARRAY;
    }

    List<Document> list = new ArrayList<Document>(myUnsavedDocuments);
    return list.toArray(new Document[list.size()]);
  }
 private void selectionChanged() {
   myBackSlashPressed.clear();
   UIUtil.invokeLaterIfNeeded(
       new Runnable() {
         @Override
         public void run() {
           updateEditorsFromProperties();
         }
       });
 }
  @Override
  public void saveDocument(@NotNull final Document document) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    if (!myUnsavedDocuments.contains(document)) return;

    try {
      doSaveDocument(document);
    } catch (IOException e) {
      handleErrorsOnSave(Collections.singletonMap(document, e));
    } catch (SaveVetoException ignored) {
    }
  }
  private void doSaveDocumentInWriteAction(@NotNull Document document, @NotNull VirtualFile file)
      throws IOException {
    if (!file.isValid()) {
      removeFromUnsaved(document);
      return;
    }

    if (!file.equals(getFile(document))) {
      registerDocument(document, file);
    }

    if (!isSaveNeeded(document, file)) {
      if (document instanceof DocumentEx) {
        ((DocumentEx) document).setModificationStamp(file.getModificationStamp());
      }
      removeFromUnsaved(document);
      updateModifiedProperty(file);
      return;
    }

    myMultiCaster.beforeDocumentSaving(document);

    LOG.assertTrue(file.isValid());

    String text = document.getText();
    String lineSeparator = getLineSeparator(document, file);
    if (!lineSeparator.equals("\n")) {
      text = StringUtil.convertLineSeparators(text, lineSeparator);
    }

    Project project = ProjectLocator.getInstance().guessProjectForFile(file);
    LoadTextUtil.write(project, file, this, text, document.getModificationStamp());

    myUnsavedDocuments.remove(document);
    LOG.assertTrue(!myUnsavedDocuments.contains(document));
    myTrailingSpacesStripper.clearLineModificationFlags(document);
  }
  @Override
  public void reloadFromDisk(@NotNull final Document document) {
    ApplicationManager.getApplication().assertIsDispatchThread();

    final VirtualFile file = getFile(document);
    assert file != null;

    if (!fireBeforeFileContentReload(file, document)) {
      return;
    }

    final Project project = ProjectLocator.getInstance().guessProjectForFile(file);
    CommandProcessor.getInstance()
        .executeCommand(
            project,
            new Runnable() {
              @Override
              public void run() {
                ApplicationManager.getApplication()
                    .runWriteAction(
                        new ExternalChangeAction.ExternalDocumentChange(document, project) {
                          @Override
                          public void run() {
                            boolean wasWritable = document.isWritable();
                            DocumentEx documentEx = (DocumentEx) document;
                            documentEx.setReadOnly(false);
                            LoadTextUtil.setCharsetWasDetectedFromBytes(file, null);
                            documentEx.replaceText(
                                LoadTextUtil.loadText(file), file.getModificationStamp());
                            documentEx.setReadOnly(!wasWritable);
                          }
                        });
              }
            },
            UIBundle.message("file.cache.conflict.action"),
            null,
            UndoConfirmationPolicy.REQUEST_CONFIRMATION);

    myUnsavedDocuments.remove(document);

    myMultiCaster.fileContentReloaded(file, document);
  }
 @Override
 public boolean isDocumentUnsaved(@NotNull Document document) {
   return myUnsavedDocuments.contains(document);
 }
 private void removeFromUnsaved(@NotNull Document document) {
   myUnsavedDocuments.remove(document);
   fireUnsavedDocumentsDropped();
   LOG.assertTrue(!myUnsavedDocuments.contains(document));
 }