diff --git a/packages/babel-traverse/src/path/ancestry.js b/packages/babel-traverse/src/path/ancestry.js index e7c3217093..8b4d2c89a1 100644 --- a/packages/babel-traverse/src/path/ancestry.js +++ b/packages/babel-traverse/src/path/ancestry.js @@ -175,6 +175,20 @@ export function getAncestry() { return paths; } +/** + * A helper to find if `this` path is an ancestor of @param maybeDescendant + */ +export function isAncestor(maybeDescendant) { + return !!maybeDescendant.findParent((parent) => parent === this); +} + +/** + * A helper to find if `this` path is a descendant of @param maybeAncestor + */ +export function isDescendant(maybeAncestor) { + return maybeAncestor.isAncestor(this); +} + export function inType() { let path = this; while (path) { diff --git a/packages/babel-traverse/test/ancestry.js b/packages/babel-traverse/test/ancestry.js new file mode 100644 index 0000000000..43e09859ef --- /dev/null +++ b/packages/babel-traverse/test/ancestry.js @@ -0,0 +1,65 @@ +let traverse = require("../lib").default; +let assert = require("assert"); +let parse = require("babylon").parse; + +describe("path/ancestry", function () { + describe("isAncestor", function () { + let ast = parse("var a = 1; 'a';"); + + it("returns true if ancestor", function() { + let paths = []; + traverse(ast, { + "Program|NumericLiteral"(path) { + paths.push(path); + }, + }); + + let [ programPath, numberPath ] = paths; + + assert(programPath.isAncestor(numberPath)); + }); + + it("returns false if not ancestor", function() { + let paths = []; + traverse(ast, { + "Program|NumericLiteral|StringLiteral"(path) { + paths.push(path); + } + }); + + let [ , numberPath, stringPath ] = paths; + + assert(!stringPath.isAncestor(numberPath)); + }); + }); + + describe("isDescendant", function () { + let ast = parse("var a = 1; 'a';"); + + it("returns true if descendant", function() { + let paths = []; + traverse(ast, { + "Program|NumericLiteral"(path) { + paths.push(path); + }, + }); + + let [ programPath, numberPath ] = paths; + + assert(numberPath.isDescendant(programPath)); + }); + + it("returns false if not descendant", function() { + let paths = []; + traverse(ast, { + "Program|NumericLiteral|StringLiteral"(path) { + paths.push(path); + } + }); + + let [ , numberPath, stringPath ] = paths; + + assert(!numberPath.isDescendant(stringPath)); + }); + }); +});