getDirTree function

List<Subgraph> getDirTree(
  1. Directory rootDir,
  2. String ignore
)

Recurses into the rootDir and gets all the subfolders as sugraphs.

Implementation

List<Subgraph> getDirTree(Directory rootDir, String ignore) {
  var dirs = [rootDir];
  var subgraphs = [
    Subgraph(rootDir.path.replaceFirst(rootDir.path, '').replaceAll('\\', '/'),
        basename(rootDir.path))
  ];
  var treeSubgraphs = <Subgraph>[];
  treeSubgraphs.add(subgraphs.first);

  var leaves = <Subgraph?>[];

  var dartFilesGlob = Glob('*.dart');
  var ignoreGlob = Glob(ignore, context: Context(current: rootDir.path));
  var alwaysIgnoreGlob =
      Glob(alwaysIgnore, context: Context(current: rootDir.path));

  // Recursively build the subgraph tree.
  // The trick is to keep track of two lists (dirs and subgraphs)
  // in the while loop at the same time.
  while (dirs.isNotEmpty) {
    var currentDir = dirs.removeAt(0);
    var currentSubgraph = subgraphs.removeAt(0);

    var dirsOnly = currentDir
        .listSync(recursive: false, followLinks: false)
        .whereType<Directory>()
        .where((dir) => !alwaysIgnoreGlob.matches(dir.path))
        .where((dir) => !ignoreGlob.matches(dir.path));
    var filesOnly = dartFilesGlob
        .listSync(root: currentDir.path, followLinks: false)
        .whereType<File>()
        .where((file) => !alwaysIgnoreGlob.matches(file.path))
        .where((file) => !ignoreGlob.matches(file.path));

    if (dirsOnly.isEmpty) {
      leaves.add(currentSubgraph);
    }

    // Add directories as subgraphs
    for (var dir in dirsOnly) {
      var subgraph = Subgraph(
          dir.path.replaceFirst(rootDir.path, '').replaceAll('\\', '/'),
          basename(dir.path));
      currentSubgraph.subgraphs.add(subgraph);
      subgraph.parent = currentSubgraph;
    }

    // Add dart files as nodes
    for (var file in filesOnly) {
      currentSubgraph.nodes
          .add(file.path.replaceFirst(rootDir.path, '').replaceAll('\\', '/'));
    }

    // Recurse breadth first
    dirs.addAll(dirsOnly);
    subgraphs.addAll(currentSubgraph.subgraphs);
  }

  // Recursively remove empty subgraphs which don't contain any dart files
  while (leaves.isNotEmpty) {
    var leaf = leaves.removeLast()!;
    if (leaf.parent != null) {
      if (leaf.nodes.isEmpty && leaf.subgraphs.isEmpty) {
        leaf.parent!.subgraphs.remove(leaf);

        // Recurse up the tree depth first
        leaves.add(leaf.parent);
      }
    }
  }

  return treeSubgraphs;
}