private static void collectClasses(PsiClass containingClass, List<? super PsiClass> classes, HashSet<? super PsiClass> visited) {
    if (!visited.add(containingClass)) return;
    Set<PsiClass> containers = new HashSet<>();
    final boolean isJUnit5 = ReadAction.compute(() -> JUnitUtil.isJUnit5(containingClass));
    ClassInheritorsSearch.search(containingClass).forEach(aClass -> {
      PsiClass container = aClass.getContainingClass();
      if (container != null && container.hasModifierProperty(PsiModifier.ABSTRACT)) {
        containers.add(container);
      }
      if (isJUnit5 && JUnitUtil.isJUnit5TestClass(aClass, true) || PsiClassUtil.isRunnableClass(aClass, true, true)) {
        classes.add(aClass);
      }
      return true;
    });

    for (PsiClass container : containers) {
      collectClasses(container, classes, visited);
    }
  }
private static void collectClasses(PsiClass containingClass, List<? super PsiClass> classes, HashSet<? super PsiClass> visited)