public boolean isErrorAnalyzingFinished(PsiFile file) {
   if (myDisposed) return false;
   Document document = PsiDocumentManager.getInstance(myProject).getCachedDocument(file);
   return document != null
       && document.getModificationStamp() == file.getModificationStamp()
       && myFileStatusMap.getFileDirtyScope(document, Pass.UPDATE_ALL) == null;
 }
 public boolean isAllAnalysisFinished(@NotNull PsiFile file) {
   if (myDisposed) return false;
   Document document = PsiDocumentManager.getInstance(myProject).getCachedDocument(file);
   return document != null
       && document.getModificationStamp() == file.getModificationStamp()
       && myFileStatusMap.allDirtyScopesAreNull(document);
 }
  public GeneralHighlightingPass(
      @NotNull Project project,
      @NotNull PsiFile file,
      @NotNull Document document,
      int startOffset,
      int endOffset,
      boolean updateAll,
      @NotNull ProperTextRange priorityRange,
      @Nullable Editor editor) {
    super(project, document, PRESENTABLE_NAME, file, true);
    myStartOffset = startOffset;
    myEndOffset = endOffset;
    myUpdateAll = updateAll;
    myPriorityRange = priorityRange;
    myEditor = editor;

    LOG.assertTrue(file.isValid());
    setId(Pass.UPDATE_ALL);
    myHasErrorElement =
        !isWholeFileHighlighting() && Boolean.TRUE.equals(myFile.getUserData(HAS_ERROR_ELEMENT));
    FileStatusMap fileStatusMap =
        ((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(myProject)).getFileStatusMap();
    myErrorFound = !isWholeFileHighlighting() && fileStatusMap.wasErrorFound(myDocument);

    myApplyCommand =
        new Runnable() {
          @Override
          public void run() {
            ProperTextRange range = new ProperTextRange(myStartOffset, myEndOffset);
            MarkupModel model = DocumentMarkupModel.forDocument(myDocument, myProject, true);
            UpdateHighlightersUtil.cleanFileLevelHighlights(myProject, Pass.UPDATE_ALL, myFile);
            final EditorColorsScheme colorsScheme = getColorsScheme();
            UpdateHighlightersUtil.setHighlightersInRange(
                myProject,
                myDocument,
                range,
                colorsScheme,
                myHighlights,
                (MarkupModelEx) model,
                Pass.UPDATE_ALL);
          }
        };

    // initial guess to show correct progress in the traffic light icon
    setProgressLimit(document.getTextLength() / 2); // approx number of PSI elements = file length/2
    myGlobalScheme = EditorColorsManager.getInstance().getGlobalScheme();
  }
 @Override
 public void restart(@NotNull PsiFile file) {
   Document document = PsiDocumentManager.getInstance(myProject).getCachedDocument(file);
   if (document == null) return;
   myFileStatusMap.markFileScopeDirty(
       document, new TextRange(0, document.getTextLength()), file.getTextLength());
   stopProcess(true);
 }
  @Override
  public void projectOpened() {
    assert !myInitialized : "Double Initializing";
    myStatusBarUpdater = new StatusBarUpdater(myProject);
    Disposer.register(myProject, myStatusBarUpdater);

    myDaemonListeners = new DaemonListeners(myProject, this, myEditorTracker);
    Disposer.register(myProject, myDaemonListeners);
    reloadScopes();

    myInitialized = true;
    myDisposed = false;
    myFileStatusMap.markAllFilesDirty();
  }
 public void restart() {
   myFileStatusMap.markAllFilesDirty();
   stopProcess(true);
 }
  @TestOnly
  public List<HighlightInfo> runPasses(
      @NotNull PsiFile file,
      @NotNull Document document,
      @NotNull TextEditor textEditor,
      @NotNull int[] toIgnore,
      boolean canChangeDocument,
      @Nullable Runnable callbackWhileWaiting) {
    assert myInitialized;
    assert !myDisposed;
    Application application = ApplicationManager.getApplication();
    application.assertIsDispatchThread();
    assert !application.isWriteAccessAllowed();

    // pump first so that queued event do not interfere
    UIUtil.dispatchAllInvocationEvents();
    UIUtil.dispatchAllInvocationEvents();

    Project project = file.getProject();
    setUpdateByTimerEnabled(false);
    FileStatusMap fileStatusMap = getFileStatusMap();
    for (int ignoreId : toIgnore) {
      fileStatusMap.markFileUpToDate(document, ignoreId);
    }
    fileStatusMap.allowDirt(canChangeDocument);

    TextEditorBackgroundHighlighter highlighter =
        (TextEditorBackgroundHighlighter) textEditor.getBackgroundHighlighter();
    final List<TextEditorHighlightingPass> passes = highlighter.getPasses(toIgnore);
    HighlightingPass[] array = passes.toArray(new HighlightingPass[passes.size()]);

    final DaemonProgressIndicator progress = createUpdateProgress();
    progress.setDebug(LOG.isDebugEnabled());
    myPassExecutorService.submitPasses(
        Collections.singletonMap((FileEditor) textEditor, array), progress, Job.DEFAULT_PRIORITY);
    try {
      while (progress.isRunning()) {
        try {
          if (progress.isCanceled() && progress.isRunning()) {
            // write action sneaked in the AWT. restart
            waitForTermination();
            Throwable savedException = PassExecutorService.getSavedException(progress);
            if (savedException != null) throw savedException;
            return runPasses(
                file, document, textEditor, toIgnore, canChangeDocument, callbackWhileWaiting);
          }
          if (callbackWhileWaiting != null) {
            callbackWhileWaiting.run();
          }
          progress.waitFor(100);
          UIUtil.dispatchAllInvocationEvents();
          Throwable savedException = PassExecutorService.getSavedException(progress);
          if (savedException != null) throw savedException;
        } catch (RuntimeException e) {
          throw e;
        } catch (Error e) {
          e.printStackTrace();
          throw e;
        } catch (Throwable e) {
          e.printStackTrace();
          throw new RuntimeException(e);
        }
      }
      UIUtil.dispatchAllInvocationEvents();
      UIUtil.dispatchAllInvocationEvents();

      return getHighlights(document, null, project);
    } finally {
      fileStatusMap.allowDirt(true);
      waitForTermination();
    }
  }