void (@NotNull Processor<? super SliceUsage> processor) { final PsiElement element = ReadAction.compute(this::getElement); ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); indicator.checkCanceled(); final HashingStrategy<SliceUsage> strategy = new HashingStrategy<>() { @Override public int hashCode(SliceUsage object) { return object.getUsageInfo().hashCode(); } @Override public boolean equals(SliceUsage o1, SliceUsage o2) { return o1.getUsageInfo().equals(o2.getUsageInfo()); } }; final class SliceUsageUniqueProcessor extends CommonProcessors.UniqueProcessor<SliceUsage> { private SliceUsageUniqueProcessor(@NotNull Processor<? super SliceUsage> processor, HashingStrategy<? super SliceUsage> strategy) { super(processor, strategy); } @Override public boolean process(SliceUsage usage) { SliceValueFilter filter = usage.params.valueFilter; if (filter != null) { PsiElement psiElement = usage.getElement(); if (psiElement != null && !filter.allowed(psiElement)) { return true; } } return ContainerUtil.and(transformToLanguageSpecificUsage(usage), super::process); } } final SliceUsageUniqueProcessor uniqueProcessor = new SliceUsageUniqueProcessor(processor, strategy); final Runnable processUsagesFlow = () -> { if (params.dataFlowToThis) { processUsagesFlownDownTo(element, uniqueProcessor); } else { processUsagesFlownFromThe(element, uniqueProcessor); } }; ReadAction.nonBlocking(processUsagesFlow).executeSynchronously(); }