void (@NotNull CompositeFilter compositeFilter, int line1, int endLine) { ThreadingAssertions.assertEventDispatchThread(); int startLine = Math.max(0, line1); Document document = getEditor().getDocument(); int startOffset = document.getLineStartOffset(startLine); String text = document.getText(new TextRange(startOffset, document.getLineEndOffset(endLine))); Document documentCopy = new DocumentImpl(text,true); documentCopy.setReadOnly(true); myJLayeredPane.startUpdating(); int currentValue = myHeavyUpdateTicket; myHeavyAlarm.addRequest(() -> { if (!compositeFilter.shouldRunHeavy()) return; try { compositeFilter.applyHeavyFilter(documentCopy, startOffset, startLine, additionalHighlight -> addFlushRequest(0, new FlushRunnable(true) { @Override public void doRun() { if (myHeavyUpdateTicket != currentValue) return; TextAttributes additionalAttributes = additionalHighlight.getTextAttributes(null); if (additionalAttributes != null) { ResultItem item = additionalHighlight.getResultItems().get(0); getHyperlinks().addHighlighter(item.getHighlightStartOffset(), item.getHighlightEndOffset(), additionalAttributes); } else { getHyperlinks().highlightHyperlinks(additionalHighlight, 0); } } }) ); } catch (IndexNotReadyException ignore) { } finally { if (myHeavyAlarm.getActiveRequestCount() <= 1) { // only the current request UIUtil.invokeLaterIfNeeded(() -> myJLayeredPane.finishUpdating()); } } }, 0); }