private static boolean shouldVisit(@NotNull VirtualFile file, @NotNull ProjectFileIndex index, @NotNull VirtualFile root) {
      if (file.is(VFileProperty.SYMLINK)) {
        if (!Registry.is("indexer.follows.symlinks")) {
          return false;
        }
        VirtualFile targetFile = file.getCanonicalFile();
        if (targetFile == null || targetFile.is(VFileProperty.SYMLINK)) {
          // Broken or recursive symlink. The second check should not happen but let's guarantee no StackOverflowError.
          return false;
        }
        if (root.equals(file)) {
          return true;
        }
        return shouldVisit(targetFile, index, root);
      }
      if (!(file instanceof VirtualFileWithId) || ((VirtualFileWithId)file).getId() <= 0) {
        return false;
      }
      if (ReadAction.compute(() -> index.isExcluded(file))) {
        return false;
      }
      return true;
    }
private static boolean shouldVisit(@NotNull VirtualFile file, @NotNull ProjectFileIndex index, @NotNull VirtualFile root)