Skip to content

Commit

Permalink
feat: #180 - Directory - isAncestorOf and isDescendantOf
Browse files Browse the repository at this point in the history
Useful for checking if a directory is a descendant of another directory or for checking if a directory is an ancestor of another directory or a source file.
  • Loading branch information
dsherret committed Dec 19, 2017
1 parent 6fa51c6 commit 7b259d9
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/factories/DirectoryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export class DirectoryCache {
this.directoriesByPath.set(path, newDirectory);

for (const orphanDir of this.orphanDirs.values()) {
if (newDirectory.isAncestorOfDir(orphanDir))
if (newDirectory.isAncestorOf(orphanDir))
this.fillParentsOfDirPath(orphanDir.getPath());
}

Expand Down
32 changes: 26 additions & 6 deletions src/fileSystem/Directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,35 @@ export class Directory {
}

/**
* Checks if a directory is an ancestor of another directory.
* @internal
* Checks if this directory is an ancestor of the provided directory.
* @param possibleDescendant - Directory or source file that's a possible descendant.
*/
isAncestorOf(possibleDescendant: Directory | SourceFile) {
return Directory.isAncestorOfDir(this, possibleDescendant);
}

/**
* Checks if this directory is a descendant of the provided directory.
* @param possibleAncestor - Directory or source file that's a possible ancestor.
*/
isAncestorOfDir(descendant: Directory) {
if (this._pathParts.length >= descendant._pathParts.length)
isDescendantOf(possibleAncestor: Directory) {
return Directory.isAncestorOfDir(possibleAncestor, this);
}

/** @internal */
private static isAncestorOfDir(ancestor: Directory, descendant: Directory | SourceFile) {
if (descendant instanceof SourceFile) {
descendant = descendant.getDirectory();
if (ancestor === descendant)
return true;
}

if (ancestor._pathParts.length >= descendant._pathParts.length)
return false;

for (let i = 0; i < this._pathParts.length; i++) {
if (this._pathParts[i] !== descendant._pathParts[i])
// more likely to be a mistake at the end, so search backwards
for (let i = ancestor._pathParts.length - 1; i >= 0; i--) {
if (ancestor._pathParts[i] !== descendant._pathParts[i])
return false;
}

Expand Down
57 changes: 57 additions & 0 deletions src/tests/fileSystem/directoryTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,63 @@ describe(nameof(Directory), () => {
});
});

describe("ancestor/descendant tests", () => {
const ast = getAst();
const root = ast.createDirectory("");
const child = ast.createDirectory("child");
const childChild = ast.createDirectory("child/child");
const otherChild = ast.createDirectory("otherChild");
const rootSourceFile = ast.createSourceFile("file.ts");

describe(nameof<Directory>(d => d.isAncestorOf), () => {
function doTest(ancestor: Directory, descendant: Directory | SourceFile, expectedValue: boolean) {
expect(ancestor.isAncestorOf(descendant)).to.equal(expectedValue);
}

it("should be an ancestor when is parent", () => {
doTest(root, child, true);
});

it("should be an ancestor when is ancestor", () => {
doTest(root, childChild, true);
});

it("should not be when a sibling", () => {
doTest(child, otherChild, false);
});

it("should not be when a child", () => {
doTest(child, root, false);
});

it("should be when a parent dir of a source file", () => {
doTest(root, rootSourceFile, true);
});
});

describe(nameof<Directory>(d => d.isDescendantOf), () => {
function doTest(descendant: Directory, ancestor: Directory, expectedValue: boolean) {
expect(descendant.isDescendantOf(ancestor)).to.equal(expectedValue);
}

it("should be a descendant when is child", () => {
doTest(child, root, true);
});

it("should be a descendant when is descendant", () => {
doTest(childChild, root, true);
});

it("should not be when a sibling", () => {
doTest(otherChild, child, false);
});

it("should not be when a parent", () => {
doTest(root, child, false);
});
});
});

describe("getting parent, child directories, and source files in directory", () => {
it("should not have a parent if no parent exists", () => {
const ast = getAst();
Expand Down

0 comments on commit 7b259d9

Please sign in to comment.