boolean runVisitors(@NotNull PsiFile psiFile,
                      @NotNull TextRange myRestrictRange,
                      @NotNull List<? extends PsiElement> elements1,
                      @NotNull LongList ranges1,
                      @NotNull List<? extends PsiElement> elements2,
                      @NotNull LongList ranges2,
                      HighlightVisitor @NotNull [] visitors,
                      boolean forceHighlightParents,
                      int chunkSize,
                      boolean myUpdateAll,
                      @NotNull Supplier<? extends HighlightInfoHolder> infoHolderProducer,
                      @NotNull TriConsumer<Object, ? super PsiElement, ? super List<? extends HighlightInfo>> resultSink) {
    List<? extends VisitorInfo> visitorInfos = ContainerUtil.map(visitors, v -> new VisitorInfo(v, new HashSet<>(), infoHolderProducer.get()));
    // first, run all visitors in parallel on all visible elements, then run all visitors in parallel on all invisible elements
    List<PsiElement> elements = ContainerUtil.concat(elements1, elements2);
    LongList ranges = new LongArrayList();
    ranges.addAll(ranges1);
    ranges.addAll(ranges2);
    if (GeneralHighlightingPass.LOG.isDebugEnabled()) {
      GeneralHighlightingPass.LOG.debug("HighlightVisitorRunner: visitors: " + Arrays.toString(visitors)+"; myRestrictRange="+myRestrictRange+"; psiFile="+psiFile);
    }
    boolean res =
      JobLauncher.getInstance().invokeConcurrentlyUnderProgress(visitorInfos, ProgressManager.getGlobalProgressIndicator(), visitorInfo -> {
        HighlightVisitor visitor = visitorInfo.visitor();
        if (GeneralHighlightingPass.LOG.isDebugEnabled()) {
          GeneralHighlightingPass.LOG.debug("HighlightVisitorRunner: running visitor: " + visitor+"("+visitor.getClass()+"); psiFile="+psiFile+"; "+Thread.currentThread());
        }
        try {
          int[] sizeAfterRunVisitor = new int[1];
          HighlightInfoHolder holder = visitorInfo.holder();
          boolean result = visitor.analyze(psiFile, myUpdateAll, holder, () -> {
            reportOutOfRunVisitorInfos(0, ANALYZE_BEFORE_RUN_VISITOR_FAKE_PSI_ELEMENT, holder, visitor, resultSink);
            runVisitor(psiFile, myRestrictRange, elements, ranges, chunkSize, visitorInfo.skipParentsSet(), holder, forceHighlightParents, visitor, resultSink);
            sizeAfterRunVisitor[0] = holder.size();
          });
          reportOutOfRunVisitorInfos(sizeAfterRunVisitor[0], ANALYZE_AFTER_RUN_VISITOR_FAKE_PSI_ELEMENT, holder, visitor, resultSink);
          if (GeneralHighlightingPass.LOG.isDebugEnabled()) {
            GeneralHighlightingPass.LOG.debug("HighlightVisitorRunner: visitor finished " + visitor + "(" + visitor.getClass() + ")" +
                                              (result ? "" : " returned false") + "; holder: "+holder.size()+" results"+"; "+Thread.currentThread());
          }
          return result;
        }
        catch (Exception e) {
          if (GeneralHighlightingPass.LOG.isDebugEnabled()) {
            GeneralHighlightingPass.LOG.debug("GHP: visitor " + visitor + "(" + visitor.getClass() + ") threw " + ExceptionUtil.getThrowableText(e)+"; "+Thread.currentThread());
          }
          throw e;
        }
      });
    if (GeneralHighlightingPass.LOG.isDebugEnabled()) {
      GeneralHighlightingPass.LOG.debug("HighlightVisitorRunner: all visitors ran; result="+res+" visitorInfos="+visitorInfos+"; "+Thread.currentThread());
    }
    return res;
  }
boolean runVisitors(@NotNull PsiFile psiFile,
                      @NotNull TextRange myRestrictRange,
                      @NotNull List<? extends PsiElement> elements1,
                      @NotNull LongList ranges1,
                      @NotNull List<? extends PsiElement> elements2,
                      @NotNull LongList ranges2,
                      HighlightVisitor @NotNull [] visitors,
                      boolean forceHighlightParents,
                      int chunkSize,
                      boolean myUpdateAll,
                      @NotNull Supplier<? extends HighlightInfoHolder> infoHolderProducer,
                      @NotNull TriConsumer<Object, ? super PsiElement, ? super List<? extends HighlightInfo>> resultSink)