void (@NotNull final ClassInheritorsSearch.SearchParameters parameters, @NotNull final Processor<? super PsiClass> consumer) { @NotNull final PsiClass baseClass = parameters.getClassToProcess(); if (baseClass instanceof PsiAnonymousClass || isFinal(baseClass)) return; final SearchScope searchScope = parameters.getScope(); Project project = PsiUtilCore.getProjectInReadAction(baseClass); if (isJavaLangObject(baseClass)) { AllClassesSearch.search(searchScope, project, parameters.getNameCondition()).allowParallelProcessing().forEach(aClass -> { ProgressManager.checkCanceled(); return isJavaLangObject(aClass) || consumer.process(aClass); }); return; } if (searchScope instanceof LocalSearchScope && JavaOverridingMethodsSearcher.isJavaOnlyScope(((LocalSearchScope)searchScope).getVirtualFiles())) { processLocalScope(project, parameters, (LocalSearchScope)searchScope, baseClass, consumer); return; } if (!parameters.isCheckDeep() && ApplicationManager.getApplication().isDispatchThread()) { // optimisation: if under EDT we've been asked for one inheritor, to improve latency do not bother to compute and cache them all DirectClassInheritorsSearch.search(baseClass, searchScope).forEach(consumer); return; } Iterable<PsiClass> cached = getOrComputeSubClasses(project, baseClass, searchScope, parameters); for (final PsiClass subClass : cached) { ProgressManager.checkCanceled(); if (subClass == null) { // PsiAnchor failed to retrieve? continue; } if (ReadAction.compute(() -> checkCandidate(subClass, parameters) && !consumer.process(subClass))) { return; } } }