private static Set<PsiJavaModule> walk(@NotNull PsiJavaModule descriptor,
                                         @NotNull Predicate<@NotNull PsiJavaModule> shouldProcessFollowingFile) {
    PsiFile descriptorFile = descriptor.getContainingFile().getOriginalFile();
    Module module = ModuleUtilCore.findModuleForFile(descriptorFile);
    if (module == null) return Set.of();

    PsiManager psiManager = PsiManager.getInstance(module.getProject());
    ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
    ModuleFileIndex fileIndex = rootManager.getFileIndex();

    // collect descriptors
    Map<PsiImportStatement, PsiJavaModule> imports = new HashMap<>();
    ImportsCollector collector = new ImportsCollector(psiManager, statement -> {
      PsiJavaModule result = imports.computeIfAbsent(statement, stmt -> findDescriptor(stmt.resolve()));
      return result == null || shouldProcessFollowingFile.test(result);
    });
    DependencyScope scope = getScope(descriptor);
    for (VirtualFile root : rootManager.getSourceRoots()) {
      DependencyScope currentScope = fileIndex.isInTestSourceContent(root) ? DependencyScope.TEST : DependencyScope.COMPILE;
      if (currentScope == scope) {
        VfsUtilCore.iterateChildrenRecursively(root, file -> file.isDirectory() ||
                                                             (file.getExtension() != null && JVM_LANGUAGES.contains(file.getExtension())),
                                               collector);
      }
    }

    // clean descriptors
    return imports.values().stream()
      .filter(Objects::nonNull)
      .filter(m -> !m.getName().equals(descriptor.getName()))
      .collect(Collectors.toCollection(() -> new TreeSet<>((o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()))));
  }
private static Set<PsiJavaModule> walk(@NotNull PsiJavaModule descriptor,
                                         @NotNull Predicate<@NotNull PsiJavaModule> shouldProcessFollowingFile)