void (@NotNull ProgressIndicator indicator) { Map<VirtualFile, IntList> files2lines = CollectionFactory.createSmallMemoryFootprintMap(); Int2ObjectMap<LastRevision> revisions = new Int2ObjectOpenHashMap<>(); ApplicationManager.getApplication().runReadAction(() -> { for (int line = 0; line < editor.getDocument().getLineCount(); line++) { indicator.checkCanceled(); VirtualFile file = getHyperlinkVirtualFile(hyperlinks.findAllHyperlinksOnLine(line)); if (file == null) continue; files2lines.computeIfAbsent(file, __ -> new IntArrayList()).add(line); } }); for (Map.Entry<VirtualFile, IntList> entry : files2lines.entrySet()) { VirtualFile file = entry.getKey(); IntList value = entry.getValue(); indicator.checkCanceled(); LastRevision revision = getLastRevision(file); if (revision == null) { continue; } synchronized (LOCK) { for (IntListIterator iterator = value.iterator(); iterator.hasNext(); ) { revisions.put(iterator.nextInt(), revision); } } myUpdateQueue.queue(new Update("update") { @Override public void run() { updateGutter(indicator, revisions); } }); } // myUpdateQueue can be disposed before the last revisions are passed to the gutter ApplicationManager.getApplication().invokeLater(() -> updateGutter(indicator, revisions)); }