private void updateByChange(@NotNull PsiElement child, @NotNull Document document, boolean whitespaceOptimizationAllowed) {
    ApplicationManager.getApplication().assertWriteIntentLockAcquired();
    PsiFile file;
    try {
      file = child.getContainingFile();
    }
    catch (PsiInvalidElementAccessException e) {
      myFileStatusMap.markAllFilesDirty(e);
      return;
    }
    if (file == null || file instanceof PsiCompiledElement) {
      myFileStatusMap.markAllFilesDirty(child);
      return;
    }
    VirtualFile virtualFile = file.getVirtualFile();
    if (virtualFile != null && !shouldHandle(virtualFile)) {
      // ignore workspace.xml
      return;
    }

    int fileLength = file.getTextLength();
    if (!file.getViewProvider().isPhysical()) {
      myFileStatusMap.markFileScopeDirty(document, new TextRange(0, fileLength), fileLength, "Non-physical file update: "+file);
      return;
    }

    TextRange existingDirtyScope = myFileStatusMap.getFileDirtyScopeForAllPassesCombined(document);
    PsiElement element = whitespaceOptimizationAllowed && UpdateHighlightersUtil.isWhitespaceOptimizationAllowed(document) ? child : child.getParent();
    while (true) {
      if (element == null || element instanceof PsiFile || element instanceof PsiDirectory) {
        myFileStatusMap.markAllFilesDirty("Top element: "+element);
        return;
      }

      PsiElement scope = getChangeHighlightingScope(element);
      if (scope != null) {
        TextRange scopeRange = scope.getTextRange();
        // if some unrelated scope already marked dirty, we shouldn't just add another scope and return,
        // because between these two dirty whitespaces might easily be some other non-whitespace PSI,
        // and this PSI element is not expected to be highlighted alone, which could lead to unexpected highlighter disappearances
        // see DaemonRespondToChangesTest.testPutArgumentsOnSeparateLinesIntentionMustNotRemoveErrorHighlighting
        if (existingDirtyScope == null || scopeRange.contains(existingDirtyScope)) {
          myFileStatusMap.markFileScopeDirty(document, scopeRange, fileLength, "Scope: " + scope);
          return;
        }
        existingDirtyScope = existingDirtyScope.union(scopeRange);
      }

      element = element.getParent();
    }
  }
private void updateByChange(@NotNull PsiElement child, @NotNull Document document, boolean whitespaceOptimizationAllowed)