@Nullable
  protected DaemonCodeAnalyzerStatus getDaemonCodeAnalyzerStatus(
      boolean fillErrorsCount, SeverityRegistrar severityRegistrar) {
    if (myFile == null
        || myProject.isDisposed()
        || !myDaemonCodeAnalyzer.isHighlightingAvailable(myFile)) return null;

    List<String> noInspectionRoots = new ArrayList<String>();
    List<String> noHighlightingRoots = new ArrayList<String>();
    FileViewProvider provider = myFile.getViewProvider();
    Set<Language> languages = provider.getLanguages();
    for (Language language : languages) {
      PsiFile root = provider.getPsi(language);
      if (!HighlightLevelUtil.shouldHighlight(root)) {
        noHighlightingRoots.add(language.getID());
      } else if (!HighlightLevelUtil.shouldInspect(root)) {
        noInspectionRoots.add(language.getID());
      }
    }
    DaemonCodeAnalyzerStatus status = new DaemonCodeAnalyzerStatus();
    status.noInspectionRoots =
        noInspectionRoots.isEmpty() ? null : ArrayUtil.toStringArray(noInspectionRoots);
    status.noHighlightingRoots =
        noHighlightingRoots.isEmpty() ? null : ArrayUtil.toStringArray(noHighlightingRoots);

    status.errorCount = errorCount.clone();
    status.rootsNumber = languages.size();
    fillDaemonCodeAnalyzerErrorsStatus(status, fillErrorsCount, severityRegistrar);
    List<TextEditorHighlightingPass> passes =
        myDaemonCodeAnalyzer.getPassesToShowProgressFor(myDocument);
    status.passStati =
        passes.isEmpty()
            ? Collections.<ProgressableTextEditorHighlightingPass>emptyList()
            : new ArrayList<ProgressableTextEditorHighlightingPass>(passes.size());
    //noinspection ForLoopReplaceableByForEach
    for (int i = 0; i < passes.size(); i++) {
      TextEditorHighlightingPass tepass = passes.get(i);
      if (!(tepass instanceof ProgressableTextEditorHighlightingPass)) continue;
      ProgressableTextEditorHighlightingPass pass = (ProgressableTextEditorHighlightingPass) tepass;

      if (pass.getProgress() < 0) continue;
      status.passStati.add(pass);
    }
    status.errorAnalyzingFinished = myDaemonCodeAnalyzer.isAllAnalysisFinished(myFile);
    status.enabled = myDaemonCodeAnalyzer.isUpdateByTimerEnabled();

    return status;
  }
  private void reportErrorsToWolf() {
    if (!myFile.getViewProvider().isPhysical()) return; // e.g. errors in evaluate expression
    Project project = myFile.getProject();
    if (!PsiManager.getInstance(project).isInProject(myFile))
      return; // do not report problems in libraries
    VirtualFile file = myFile.getVirtualFile();
    if (file == null) return;

    List<Problem> problems = convertToProblems(getInfos(), file, myHasErrorElement);
    WolfTheProblemSolver wolf = WolfTheProblemSolver.getInstance(project);

    boolean hasErrors = DaemonCodeAnalyzerImpl.hasErrors(project, getDocument());
    if (!hasErrors || isWholeFileHighlighting()) {
      wolf.reportProblems(file, problems);
    } else {
      wolf.weHaveGotProblems(file, problems);
    }
  }
 @NotNull
 private static List<HighlightInfo> getVisibleHighlights(
     final int startOffset, final int endOffset, Project project, final Editor editor) {
   final List<HighlightInfo> highlights = new ArrayList<HighlightInfo>();
   DaemonCodeAnalyzerImpl.processHighlights(
       editor.getDocument(),
       project,
       null,
       startOffset,
       endOffset,
       new Processor<HighlightInfo>() {
         @Override
         public boolean process(HighlightInfo info) {
           if (info.hasHint() && !editor.getFoldingModel().isOffsetCollapsed(info.startOffset)) {
             highlights.add(info);
           }
           return true;
         }
       });
   return highlights;
 }
  @Override
  protected void collectInformationWithProgress(final ProgressIndicator progress) {
    final Set<HighlightInfo> gotHighlights = new THashSet<HighlightInfo>(100);
    final Set<HighlightInfo> outsideResult = new THashSet<HighlightInfo>(100);

    DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(myProject);
    HighlightVisitor[] highlightVisitors = getHighlightVisitors();
    final HighlightVisitor[] filteredVisitors = filterVisitors(highlightVisitors, myFile);
    final List<PsiElement> inside = new ArrayList<PsiElement>();
    final List<PsiElement> outside = new ArrayList<PsiElement>();
    try {
      Divider.divideInsideAndOutside(
          myFile,
          myStartOffset,
          myEndOffset,
          myPriorityRange,
          inside,
          outside,
          HighlightLevelUtil.AnalysisLevel.HIGHLIGHT,
          false);

      setProgressLimit((long) (inside.size() + outside.size()));

      final boolean forceHighlightParents = forceHighlightParents();

      if (!isDumbMode()) {
        highlightTodos(
            myFile,
            myDocument.getCharsSequence(),
            myStartOffset,
            myEndOffset,
            progress,
            myPriorityRange,
            gotHighlights,
            outsideResult);
      }

      collectHighlights(
          inside,
          new Runnable() {
            @Override
            public void run() {
              // all infos for the "injected fragment for the host which is inside" are indeed
              // inside
              // but some of the infos for the "injected fragment for the host which is outside" can
              // be still inside
              Set<HighlightInfo> injectedResult = new THashSet<HighlightInfo>();
              final Set<PsiFile> injected = new THashSet<PsiFile>();
              getInjectedPsiFiles(inside, outside, progress, injected);
              if (!addInjectedPsiHighlights(
                  injected, progress, Collections.synchronizedSet(injectedResult)))
                throw new ProcessCanceledException();
              final List<HighlightInfo> injectionsOutside =
                  new ArrayList<HighlightInfo>(gotHighlights.size());

              Set<HighlightInfo> result;
              synchronized (injectedResult) {
                // sync here because all writes happened in another thread
                result = injectedResult;
              }
              for (HighlightInfo info : result) {
                if (myPriorityRange.containsRange(info.getStartOffset(), info.getEndOffset())) {
                  gotHighlights.add(info);
                } else {
                  // nonconditionally apply injected results regardless whether they are in
                  // myStartOffset,myEndOffset
                  injectionsOutside.add(info);
                }
              }

              if (outsideResult.isEmpty() && injectionsOutside.isEmpty()) {
                return; // apply only result (by default apply command) and only within inside
              }

              final ProperTextRange priorityIntersection =
                  myPriorityRange.intersection(new TextRange(myStartOffset, myEndOffset));
              if ((!inside.isEmpty() || !gotHighlights.isEmpty())
                  && priorityIntersection
                      != null) { // do not apply when there were no elements to highlight
                // clear infos found in visible area to avoid applying them twice
                final List<HighlightInfo> toApplyInside =
                    new ArrayList<HighlightInfo>(gotHighlights);
                myHighlights.addAll(toApplyInside);
                gotHighlights.clear();
                gotHighlights.addAll(outsideResult);
                final long modificationStamp = myDocument.getModificationStamp();
                UIUtil.invokeLaterIfNeeded(
                    new Runnable() {
                      @Override
                      public void run() {
                        if (myProject.isDisposed()
                            || modificationStamp != myDocument.getModificationStamp()) return;
                        MarkupModel markupModel =
                            DocumentMarkupModel.forDocument(myDocument, myProject, true);

                        UpdateHighlightersUtil.setHighlightersInRange(
                            myProject,
                            myDocument,
                            priorityIntersection,
                            getColorsScheme(),
                            toApplyInside,
                            (MarkupModelEx) markupModel,
                            Pass.UPDATE_ALL);
                        if (myEditor != null) {
                          new ShowAutoImportPass(myProject, myFile, myEditor)
                              .applyInformationToEditor();
                        }
                      }
                    });
              }

              myApplyCommand =
                  new Runnable() {
                    @Override
                    public void run() {
                      ProperTextRange range = new ProperTextRange(myStartOffset, myEndOffset);

                      List<HighlightInfo> toApply = new ArrayList<HighlightInfo>();
                      for (HighlightInfo info : gotHighlights) {
                        if (!range.containsRange(info.getStartOffset(), info.getEndOffset()))
                          continue;
                        if (!myPriorityRange.containsRange(
                            info.getStartOffset(), info.getEndOffset())) {
                          toApply.add(info);
                        }
                      }
                      toApply.addAll(injectionsOutside);

                      UpdateHighlightersUtil.setHighlightersOutsideRange(
                          myProject,
                          myDocument,
                          toApply,
                          getColorsScheme(),
                          myStartOffset,
                          myEndOffset,
                          myPriorityRange,
                          Pass.UPDATE_ALL);
                    }
                  };
            }
          },
          outside,
          progress,
          filteredVisitors,
          gotHighlights,
          forceHighlightParents);

      if (myUpdateAll) {
        ((DaemonCodeAnalyzerImpl) daemonCodeAnalyzer)
            .getFileStatusMap()
            .setErrorFoundFlag(myDocument, myErrorFound);
      }
    } finally {
      incVisitorUsageCount(-1);
    }
    myHighlights.addAll(gotHighlights);
  }
  @NotNull
  protected DaemonCodeAnalyzerStatus getDaemonCodeAnalyzerStatus(
      @NotNull SeverityRegistrar severityRegistrar) {
    DaemonCodeAnalyzerStatus status = new DaemonCodeAnalyzerStatus();
    if (myFile == null) {
      status.reasonWhyDisabled = "No file";
      status.errorAnalyzingFinished = true;
      return status;
    }
    if (myProject != null && myProject.isDisposed()) {
      status.reasonWhyDisabled = "Project is disposed";
      status.errorAnalyzingFinished = true;
      return status;
    }
    if (!myDaemonCodeAnalyzer.isHighlightingAvailable(myFile)) {
      if (!myFile.isPhysical()) {
        status.reasonWhyDisabled = "File is generated";
        status.errorAnalyzingFinished = true;
        return status;
      } else if (myFile instanceof PsiCompiledElement) {
        status.reasonWhyDisabled = "File is decompiled";
        status.errorAnalyzingFinished = true;
        return status;
      }
      final FileType fileType = myFile.getFileType();
      if (fileType.isBinary()) {
        status.reasonWhyDisabled = "File is binary";
        status.errorAnalyzingFinished = true;
        return status;
      }
      status.reasonWhyDisabled = "Highlighting is disabled for this file";
      status.errorAnalyzingFinished = true;
      return status;
    }

    FileViewProvider provider = myFile.getViewProvider();
    Set<Language> languages = provider.getLanguages();
    HighlightingSettingsPerFile levelSettings = HighlightingSettingsPerFile.getInstance(myProject);
    boolean shouldHighlight = languages.isEmpty();
    for (Language language : languages) {
      PsiFile root = provider.getPsi(language);
      FileHighlightingSetting level = levelSettings.getHighlightingSettingForRoot(root);
      shouldHighlight |= level != FileHighlightingSetting.SKIP_HIGHLIGHTING;
    }
    if (!shouldHighlight) {
      status.reasonWhyDisabled = "Highlighting level is None";
      status.errorAnalyzingFinished = true;
      return status;
    }

    if (HeavyProcessLatch.INSTANCE.isRunning()) {
      status.reasonWhySuspended =
          StringUtil.defaultIfEmpty(
              HeavyProcessLatch.INSTANCE.getRunningOperationName(), "Heavy operation is running");
      status.errorAnalyzingFinished = true;
      return status;
    }

    status.errorCount = errorCount.clone();
    fillDaemonCodeAnalyzerErrorsStatus(status, severityRegistrar);
    List<TextEditorHighlightingPass> passes =
        myDaemonCodeAnalyzer.getPassesToShowProgressFor(myDocument);
    status.passStati =
        passes.isEmpty()
            ? Collections.<ProgressableTextEditorHighlightingPass>emptyList()
            : new ArrayList<>(passes.size());
    //noinspection ForLoopReplaceableByForEach
    for (int i = 0; i < passes.size(); i++) {
      TextEditorHighlightingPass tepass = passes.get(i);
      if (!(tepass instanceof ProgressableTextEditorHighlightingPass)) continue;
      ProgressableTextEditorHighlightingPass pass = (ProgressableTextEditorHighlightingPass) tepass;

      if (pass.getProgress() < 0) continue;
      status.passStati.add(pass);
    }
    status.errorAnalyzingFinished = myDaemonCodeAnalyzer.isAllAnalysisFinished(myFile);
    status.reasonWhySuspended =
        myDaemonCodeAnalyzer.isUpdateByTimerEnabled() ? null : "Highlighting is paused temporarily";

    return status;
  }