in src/workspace-tree/bazel_workspace_folder_tree_item.ts [77:143]
private buildPackageTree(
packagePaths: string[],
startIndex: number,
endIndex: number,
treeItems: BazelPackageTreeItem[],
parentPackagePath: string,
) {
// We can assume that the caller has sorted the packages, so we scan them to
// find groupings into which we should traverse more deeply. For example, if
// we have the following structure:
//
// foo
// foo/bar
// foo/baz
//
// ...then groupStart will point to "foo" and groupEnd will point to the
// index after "foo/baz", indicating that they share a common prefix, that
// "foo" should be its own node, and then we should recurse into that group
// to create child nodes. Then, if we have the following structure:
//
// foo/bar
// foo/baz
//
// ...then groupStart will point to "foo/bar", but since it's not a prefix
// of "foo/baz", then it becomes its own group (and thus node) at that
// level, and the same happens subsequently for "foo/bar".
//
// This means we only create intermediate tree nodes for directories that
// actually represent packages (i.e., contain a BUILD file), and collapse
// intermediate directories that don't.
let groupStart = startIndex;
while (groupStart < endIndex) {
const packagePath = packagePaths[groupStart];
let groupEnd = groupStart + 1;
// Make sure to check for a slash after the prefix so that we don't
// erroneously collapse something like "foo" and "foobar".
while (
groupEnd < endIndex &&
packagePaths[groupEnd].startsWith(packagePath + "/")
) {
groupEnd++;
}
// At this point, groupStart points to a prefix and the elements at
// (groupStart + 1) to groupEnd are preceded by that prefix. We create a
// tree node for the element at groupStart and then recursively call the
// algorithm again to group its children.
const item = new BazelPackageTreeItem(
this.workspaceInfo,
packagePath,
parentPackagePath,
);
treeItems.push(item);
this.buildPackageTree(
packagePaths,
groupStart + 1,
groupEnd,
item.directSubpackages,
packagePath,
);
// Move our index to start looking for more groups in the next iteration
// of the loop.
groupStart = groupEnd;
}
}