public static void iterateRecursively(@NotNull final VirtualFile root,
                                        @NotNull final ContentIterator processor,
                                        @Nullable final ProgressIndicator indicator,
                                        @Nullable final Set<? super VirtualFile> visitedRoots,
                                        @Nullable final ProjectFileIndex projectFileIndex) {
    VirtualFileFilter acceptFilter = file -> {
      if (indicator != null) {
        indicator.checkCanceled();
      }
      if (visitedRoots != null && !root.equals(file) && file.isDirectory() && !visitedRoots.add(file)) {
        return false;
      }
      return projectFileIndex == null || !ReadAction.compute(() -> projectFileIndex.isExcluded(file));
    };

    VirtualFileFilter symlinkFilter = file -> {
      if (acceptFilter.accept(file)) {
        if (file.is(VFileProperty.SYMLINK)) {
          if (!Registry.is("indexer.follows.symlinks")) {
            return false;
          }
          VirtualFile canonicalFile = file.getCanonicalFile();
          if (canonicalFile != null) {
            return acceptFilter.accept(canonicalFile);
          }
        }
        return true;
      }
      return false;
    };

    VfsUtilCore.iterateChildrenRecursively(root, symlinkFilter, processor);
  }
public static void iterateRecursively(@NotNull final VirtualFile root,
                                        @NotNull final ContentIterator processor,
                                        @Nullable final ProgressIndicator indicator,
                                        @Nullable final Set<? super VirtualFile> visitedRoots,
                                        @Nullable final ProjectFileIndex projectFileIndex)