void () { Long stamp = myEditor.getUserData(LAST_TIME_INDENTS_BUILT); if (stamp != null && stamp.longValue() == nowStamp()) return; List<RangeHighlighter> oldHighlighters = myEditor.getUserData(INDENT_HIGHLIGHTERS_IN_EDITOR_KEY); List<RangeHighlighter> newHighlighters = new ArrayList<>(); MarkupModel mm = myEditor.getMarkupModel(); int curRange = 0; if (oldHighlighters != null) { // after document change some range highlighters could have become invalid, or the order could have been broken oldHighlighters.sort(Comparator.comparing((RangeHighlighter h) -> !h.isValid()) .thenComparing(Segment.BY_START_OFFSET_THEN_END_OFFSET)); int curHighlight = 0; while (curRange < myRanges.size() && curHighlight < oldHighlighters.size()) { TextRange range = myRanges.get(curRange); RangeHighlighter highlighter = oldHighlighters.get(curHighlight); if (!highlighter.isValid()) break; int cmp = compare(range, highlighter); if (cmp < 0) { newHighlighters.add(createHighlighter(mm, range)); curRange++; } else if (cmp > 0) { highlighter.dispose(); curHighlight++; } else { newHighlighters.add(highlighter); curHighlight++; curRange++; } } for (; curHighlight < oldHighlighters.size(); curHighlight++) { RangeHighlighter highlighter = oldHighlighters.get(curHighlight); if (!highlighter.isValid()) break; highlighter.dispose(); } } int startRangeIndex = curRange; DocumentUtil.executeInBulk(myDocument, myRanges.size() > 10000, () -> { for (int i = startRangeIndex; i < myRanges.size(); i++) { newHighlighters.add(createHighlighter(mm, myRanges.get(i))); } }); myEditor.putUserData(INDENT_HIGHLIGHTERS_IN_EDITOR_KEY, newHighlighters); myEditor.putUserData(LAST_TIME_INDENTS_BUILT, nowStamp()); myEditor.getIndentsModel().assumeIndents(myDescriptors); }