void (@NotNull DocumentEvent event) { if (myStopTrackingDocuments || myProject.isDisposed()) return; Document document = event.getDocument(); VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document); boolean isRelevant = virtualFile != null && isRelevant(virtualFile); FileViewProvider viewProvider = getCachedViewProvider(document); if (viewProvider == null) { handleCommitWithoutPsi(document); return; } boolean inMyProject = viewProvider.getManager() == myPsiManager; if (!isRelevant || !inMyProject) { clearUncommittedInfo(document); return; } List<PsiFile> files = viewProvider.getAllFiles(); if (files.isEmpty()) { handleCommitWithoutPsi(document); return; } boolean commitNecessary = !ContainerUtil.exists(files, file -> PsiToDocumentSynchronizer.isInsideAtomicChange(file) || !(file instanceof PsiFileImpl)); Application application = ApplicationManager.getApplication(); boolean forceCommit = application.hasWriteAction(ExternalChangeAction.class) && (SystemProperties.getBooleanProperty("idea.force.commit.on.external.change", false) || application.isHeadlessEnvironment() && !application.isUnitTestMode()); // Consider that it's worth to perform complete re-parse instead of merge if the whole document text is replaced and // current document lines number is roughly above 5000. This makes sense in situations when external change is performed // for the huge file (that causes the whole document to be reloaded and 'merge' way takes a while to complete). if (event.isWholeTextReplaced() && document.getTextLength() > 100000) { document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE); } if (commitNecessary) { assert !(document instanceof DocumentWindow); myUncommittedDocuments.add(document); if (forceCommit) { commitDocument(document); } else if (!document.isInBulkUpdate() && myPerformBackgroundCommit) { retainProviderAndCommitAsync(document, event, ModalityState.defaultModalityState()); } } else { clearUncommittedInfo(document); } }