private static PsiClass @NotNull [] getOrCalculateDirectSubClasses(@NotNull Project project,
                                                                     @NotNull PsiClass baseClass,
                                                                     @NotNull DirectClassInheritorsSearch.SearchParameters parameters) {
    ConcurrentMap<PsiClass, PsiClass[]> map = HighlightingCaches.getInstance(project).DIRECT_SUB_CLASSES;
    PsiClass[] cache = map.get(baseClass);
    if (cache != null) {
      return cache;
    }

    final String baseClassName = ReadAction.compute(baseClass::getName);
    if (StringUtil.isEmpty(baseClassName)) {
      return PsiClass.EMPTY_ARRAY;
    }
    cache = calculateDirectSubClasses(project, baseClass, baseClassName, parameters);
    // for non-physical elements ignore the cache completely because non-physical elements created so often/unpredictably so I can't figure out when to clear caches in this case
    if (ReadAction.compute(baseClass::isPhysical)) {
      cache = ConcurrencyUtil.cacheOrGet(map, baseClass, cache);
    }
    return cache;
  }
private static PsiClass @NotNull [] getOrCalculateDirectSubClasses(@NotNull Project project,
                                                                     @NotNull PsiClass baseClass,
                                                                     @NotNull DirectClassInheritorsSearch.SearchParameters parameters)