void (@NotNull List<? extends PsiElement> elements, @NotNull LongList ranges, int chunkSize, @NotNull Set<? super PsiElement> skipParentsSet, @NotNull HighlightInfoHolder holder, @NotNull List<? super HighlightInfo> insideResult, @NotNull List<? super HighlightInfo> outsideResult, boolean forceHighlightParents, HighlightVisitor @NotNull [] visitors, @NotNull LongStack nestedRange, @NotNull Stack<List<HighlightInfo>> nestedInfos) { boolean failed = false; int nextLimit = chunkSize; for (int i = 0; i < elements.size(); i++) { PsiElement element = elements.get(i); ProgressManager.checkCanceled(); PsiElement parent = element.getParent(); if (element != getFile() && !skipParentsSet.isEmpty() && element.getFirstChild() != null && skipParentsSet.contains(element) && parent != null) { skipParentsSet.add(parent); continue; } if (element instanceof PsiErrorElement) { myHasErrorElement = true; } for (HighlightVisitor visitor : visitors) { try { visitor.visit(element); } catch (ProcessCanceledException | IndexNotReadyException | AlreadyDisposedException e) { throw e; } catch (Exception e) { if (!failed) { LOG.error("In file: " + getFile().getViewProvider().getVirtualFile(), e); } failed = true; } } if (i == nextLimit) { advanceProgress(chunkSize); nextLimit = i + chunkSize; } long elementRange = ranges.getLong(i); List<HighlightInfo> infosForThisRange = holder.size() == 0 ? null : new ArrayList<>(holder.size()); for (int j = 0; j < holder.size(); j++) { HighlightInfo info = holder.get(j); if (!myRestrictRange.contains(info)) continue; List<? super HighlightInfo> result = myPriorityRange.contains(info) && !(element instanceof PsiFile) ? insideResult : outsideResult; result.add(info); 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(elementRange); infosForThisRange.add(info); } holder.clear(); // include infos which we got while visiting nested elements with the same range while (!nestedRange.empty() && TextRangeScalarUtil.contains(elementRange, nestedRange.peek())) { long oldRange = nestedRange.pop(); List<HighlightInfo> oldInfos = nestedInfos.pop(); if (elementRange == oldRange) { if (infosForThisRange == null) { infosForThisRange = oldInfos; } else if (oldInfos != null) { infosForThisRange.addAll(oldInfos); } } } nestedRange.push(elementRange); nestedInfos.push(infosForThisRange); if (parent == null || !hasSameRangeAsParent(parent, element)) { myHighlightInfoProcessor.allHighlightsForRangeAreProduced(myHighlightingSession, elementRange, infosForThisRange); } } advanceProgress(elements.size() - (nextLimit-chunkSize)); }