private static boolean processDirectInheritors(
      final PyClass superClass, final Processor<? super PyClass> consumer, final boolean checkDeep, final Set<PyClass> processed
  ) {
    return ReadAction.compute(() -> {
      final String superClassName = superClass.getName();
      if (superClassName == null || IGNORED_BASES.contains(superClassName)) {
        return true;  // we don't want to look for inheritors of overly general classes
      }
      if (processed.contains(superClass)) return true;
      processed.add(superClass);
      Project project = superClass.getProject();
      final Collection<PyClass> candidates = StubIndex.getElements(PySuperClassIndex.KEY, superClassName, project,
                                                                   ProjectScope.getAllScope(project), PyClass.class);
      for (PyClass candidate : candidates) {
        final PyClass[] classes = candidate.getSuperClasses(null);
        for (PyClass superClassCandidate : classes) {
          if (superClassCandidate.isEquivalentTo(superClass)) {
            if (!consumer.process(candidate)) {
              return false;
            }
            if (checkDeep && !processDirectInheritors(candidate, consumer, checkDeep, processed)) return false;
            break;
          }
        }
      }
      return true;
    });
  }
private static boolean processDirectInheritors(
      final PyClass superClass, final Processor<? super PyClass> consumer, final boolean checkDeep, final Set<PyClass> processed
  )