private static void processInheritors(@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;
      }
    }
  }
private static void processInheritors(@NotNull final ClassInheritorsSearch.SearchParameters parameters,
                                        @NotNull final Processor<? super PsiClass> consumer)