private static void runVisitor(@NotNull PsiFile psiFile,
                                  @NotNull TextRange myRestrictRange,
                                  @NotNull List<? extends PsiElement> elements,
                                  @NotNull LongList ranges,
                                  int chunkSize,
                                  @NotNull Set<? super PsiElement> skipParentsSet,
                                  @NotNull HighlightInfoHolder holder,
                                  boolean forceHighlightParents,
                                  @NotNull HighlightVisitor visitor,
                                  @NotNull TriConsumer<Object, ? super PsiElement, ? super List<? extends HighlightInfo>> resultSink) {
    boolean failed = false;
    int nextLimit = chunkSize;
    List<HighlightInfo> infos = new ArrayList<>();
    Class<? extends @NotNull HighlightVisitor> toolId = visitor.getClass();
    for (int i = 0; i < elements.size(); i++) {
      PsiElement psiElement = elements.get(i);
      ProgressManager.checkCanceled();

      PsiElement parent = psiElement.getParent();
      if (psiElement != psiFile && !skipParentsSet.isEmpty() && psiElement.getFirstChild() != null && skipParentsSet.contains(psiElement) && parent != null) {
        skipParentsSet.add(parent);
      }
      else {
        int oldSize = holder.size();
        try {
          visitor.visit(psiElement);
        }
        catch (ProcessCanceledException | IndexNotReadyException | AlreadyDisposedException e) {
          throw e;
        }
        catch (Exception e) {
          if (!failed) {
            GeneralHighlightingPass.LOG.error("In file: " + psiFile.getViewProvider().getVirtualFile(), e);
          }
          failed = true;
        }
        for (int j = oldSize; j < holder.size(); j++) {
          HighlightInfo info = holder.get(j);

          if (!myRestrictRange.contains(info)) continue;
          boolean isError = info.getSeverity() == HighlightSeverity.ERROR;
          if (isError) {
            if (!forceHighlightParents && parent != null) {
              skipParentsSet.add(parent);
            }
            //myErrorFound = true;
          }
          // if this highlight info range is contained inside the current element range we are visiting
          // that means we can clear this highlight as soon as visitors won't produce any highlights during visiting the same range next time.
          // We also know that we can remove a syntax error element.
          info.setVisitingTextRange(psiFile, psiFile.getFileDocument(), ranges.getLong(i));
          info.toolId = toolId;
          infos.add(info);
        }
      }
      resultSink.accept(toolId, psiElement, infos);
      infos.clear();
      if (i == nextLimit) {
        //advanceProgress(chunkSize);
        nextLimit = i + chunkSize;
      }
    }
    //advanceProgress(elements.size() - (nextLimit-chunkSize));
  }
private static void runVisitor(@NotNull PsiFile psiFile,
                                  @NotNull TextRange myRestrictRange,
                                  @NotNull List<? extends PsiElement> elements,
                                  @NotNull LongList ranges,
                                  int chunkSize,
                                  @NotNull Set<? super PsiElement> skipParentsSet,
                                  @NotNull HighlightInfoHolder holder,
                                  boolean forceHighlightParents,
                                  @NotNull HighlightVisitor visitor,
                                  @NotNull TriConsumer<Object, ? super PsiElement, ? super List<? extends HighlightInfo>> resultSink)