@Override
    public void visitFile(PsiFile file) {
      final VirtualFile virtualFile = file.getVirtualFile();
      if (virtualFile == null) {
        return;
      }

      final Project project = file.getProject();
      Document document = PsiDocumentManager.getInstance(project).getDocument(file);
      if (document == null) return;
      final HighlightInfoFilter[] filters =
          ApplicationManager.getApplication()
              .getExtensions(HighlightInfoFilter.EXTENSION_POINT_NAME);
      GeneralHighlightingPass pass =
          new GeneralHighlightingPass(project, file, document, 0, file.getTextLength(), true) {
            @NotNull
            @Override
            protected HighlightVisitor[] createHighlightVisitors() {
              return new HighlightVisitor[] {
                new DefaultHighlightVisitor(project, highlightErrorElements, runAnnotators, true)
              };
            }

            @Override
            protected HighlightInfoHolder createInfoHolder(final PsiFile file) {
              return new HighlightInfoHolder(file, getColorsScheme(), filters) {
                @Override
                public boolean add(@Nullable HighlightInfo info) {
                  if (info == null) return true;
                  if (info.type == HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT) return true;
                  if (info.getSeverity() == HighlightSeverity.INFORMATION) return true;

                  result.add(Pair.create(file, info));

                  return true;
                }
              };
            }

            @Override
            protected void killAbandonedHighlightsUnder(
                @NotNull TextRange range,
                @Nullable List<HighlightInfo> holder,
                @NotNull ProgressIndicator progress) {
              // do not mess with real editor highlights
            }

            @Override
            protected boolean isFailFastOnAcquireReadAction() {
              return false;
            }
          };
      DaemonProgressIndicator progress = new DaemonProgressIndicator();
      progress.start();
      pass.collectInformation(progress);
    }
 private synchronized DaemonProgressIndicator createUpdateProgress() {
   DaemonProgressIndicator progress =
       new DaemonProgressIndicator() {
         @Override
         public void stopIfRunning() {
           super.stopIfRunning();
           myProject.getMessageBus().syncPublisher(DAEMON_EVENT_TOPIC).daemonFinished();
         }
       };
   progress.start();
   myUpdateProgress = progress;
   return progress;
 }
  public DaemonCodeAnalyzerImpl(
      @NotNull Project project,
      DaemonCodeAnalyzerSettings daemonCodeAnalyzerSettings,
      EditorTracker editorTracker) {
    myProject = project;

    mySettings = daemonCodeAnalyzerSettings;
    myEditorTracker = editorTracker;
    myLastSettings = (DaemonCodeAnalyzerSettings) mySettings.clone();

    myFileStatusMap = new FileStatusMap(myProject);
    myPassExecutorService =
        new PassExecutorService(myProject) {
          @Override
          protected void afterApplyInformationToEditor(
              final TextEditorHighlightingPass pass,
              @NotNull final FileEditor fileEditor,
              final ProgressIndicator updateProgress) {
            if (fileEditor instanceof TextEditor) {
              log(updateProgress, pass, "Apply ");
              Editor editor = ((TextEditor) fileEditor).getEditor();
              repaintErrorStripeRenderer(editor);
            }
          }

          @Override
          protected boolean isDisposed() {
            return myDisposed || super.isDisposed();
          }
        };
    Disposer.register(project, myPassExecutorService);
    Disposer.register(project, myFileStatusMap);
    DaemonProgressIndicator.setDebug(LOG.isDebugEnabled());
  }
  private synchronized void cancelUpdateProgress(final boolean start, @NonNls String reason) {
    PassExecutorService.log(myUpdateProgress, null, reason, start);
    myModificationCount++;

    if (myUpdateProgress != null) {
      myUpdateProgress.cancel();
      myPassExecutorService.cancelAll(false);
      myUpdateProgress = null;
    }
  }
 @TestOnly
 static Throwable getSavedException(@NotNull DaemonProgressIndicator indicator) {
   return indicator.getUserData(THROWABLE_KEY);
 }
 private static void saveException(
     @NotNull Throwable e, @NotNull DaemonProgressIndicator indicator) {
   indicator.putUserDataIfAbsent(THROWABLE_KEY, e);
 }
 private void applyInformationToEditorsLater(
     @NotNull final FileEditor fileEditor,
     @NotNull final TextEditorHighlightingPass pass,
     @NotNull final DaemonProgressIndicator updateProgress,
     @NotNull final AtomicInteger threadsToStartCountdown) {
   ApplicationManager.getApplication()
       .invokeLater(
           (DumbAwareRunnable)
               () -> {
                 if (isDisposed() || myProject.isDisposed()) {
                   updateProgress.cancel();
                 }
                 if (updateProgress.isCanceled()) {
                   log(updateProgress, pass, " is canceled during apply, sorry");
                   return;
                 }
                 Document document = pass.getDocument();
                 try {
                   if (fileEditor.getComponent().isDisplayable()
                       || ApplicationManager.getApplication().isUnitTestMode()) {
                     pass.applyInformationToEditor();
                     FileStatusMap fileStatusMap =
                         DaemonCodeAnalyzerEx.getInstanceEx(myProject).getFileStatusMap();
                     if (document != null) {
                       fileStatusMap.markFileUpToDate(document, pass.getId());
                     }
                     log(updateProgress, pass, " Applied");
                   }
                 } catch (ProcessCanceledException e) {
                   log(updateProgress, pass, "Error " + e);
                   throw e;
                 } catch (RuntimeException e) {
                   VirtualFile file =
                       document == null
                           ? null
                           : FileDocumentManager.getInstance().getFile(document);
                   FileType fileType = file == null ? null : file.getFileType();
                   String message =
                       "Exception while applying information to "
                           + fileEditor
                           + "("
                           + fileType
                           + ")";
                   log(updateProgress, pass, message + e);
                   throw new RuntimeException(message, e);
                 }
                 if (threadsToStartCountdown.decrementAndGet() == 0) {
                   log(updateProgress, pass, "Stopping ");
                   updateProgress.stopIfRunning();
                 } else {
                   log(
                       updateProgress,
                       pass,
                       "Finished but there are passes in the queue: "
                           + threadsToStartCountdown.get());
                 }
               },
           Registry.is("ide.perProjectModality")
               ? ModalityState.defaultModalityState()
               : ModalityState.stateForComponent(fileEditor.getComponent()));
 }
    private void doRun() {
      if (myUpdateProgress.isCanceled()) return;

      log(myUpdateProgress, myPass, "Started. ");

      for (ScheduledPass successor : mySuccessorsOnSubmit) {
        int predecessorsToRun = successor.myRunningPredecessorsCount.decrementAndGet();
        if (predecessorsToRun == 0) {
          submit(successor);
        }
      }

      ProgressManager.getInstance()
          .executeProcessUnderProgress(
              () -> {
                boolean success =
                    ApplicationManagerEx.getApplicationEx()
                        .tryRunReadAction(
                            () -> {
                              try {
                                if (DumbService.getInstance(myProject).isDumb()
                                    && !DumbService.isDumbAware(myPass)) {
                                  return;
                                }

                                if (!myUpdateProgress.isCanceled() && !myProject.isDisposed()) {
                                  myPass.collectInformation(myUpdateProgress);
                                }
                              } catch (ProcessCanceledException e) {
                                log(myUpdateProgress, myPass, "Canceled ");

                                if (!myUpdateProgress.isCanceled()) {
                                  myUpdateProgress.cancel(
                                      e); // in case when some smart asses throw PCE just for fun
                                }
                              } catch (RuntimeException | Error e) {
                                myUpdateProgress.cancel(e);
                                LOG.error(e);
                                throw e;
                              }
                            });

                if (!success) {
                  myUpdateProgress.cancel();
                }
              },
              myUpdateProgress);

      log(myUpdateProgress, myPass, "Finished. ");

      if (!myUpdateProgress.isCanceled()) {
        applyInformationToEditorsLater(
            myFileEditor, myPass, myUpdateProgress, myThreadsToStartCountdown);
        for (ScheduledPass successor : mySuccessorsOnCompletion) {
          int predecessorsToRun = successor.myRunningPredecessorsCount.decrementAndGet();
          if (predecessorsToRun == 0) {
            submit(successor);
          }
        }
      }
    }
 public synchronized boolean isRunning() {
   return myUpdateProgress != null && !myUpdateProgress.isCanceled();
 }
  @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();
    }
  }