Skip to content

Commit

Permalink
Add getBindingIdentifierPaths/getOuterBindingIdentifierPaths (babel#4876
Browse files Browse the repository at this point in the history
)
  • Loading branch information
boopathi authored and panagosg7 committed Jan 17, 2017
1 parent 454b9a4 commit 95f2048
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
61 changes: 61 additions & 0 deletions packages/babel-traverse/src/path/family.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,64 @@ export function getBindingIdentifiers(duplicates?) {
export function getOuterBindingIdentifiers(duplicates?) {
return t.getOuterBindingIdentifiers(this.node, duplicates);
}

// original source - https://github.com/babel/babel/blob/master/packages/babel-types/src/retrievers.js
// path.getBindingIdentifiers returns nodes where the following re-implementation
// returns paths
export function getBindingIdentifierPaths(duplicates = false, outerOnly = false) {
let path = this;
let search = [].concat(path);
let ids = Object.create(null);

while (search.length) {
let id = search.shift();
if (!id) continue;
if (!id.node) continue;

let keys = t.getBindingIdentifiers.keys[id.node.type];

if (id.isIdentifier()) {
if (duplicates) {
let _ids = ids[id.node.name] = ids[id.node.name] || [];
_ids.push(id);
} else {
ids[id.node.name] = id;
}
continue;
}

if (id.isExportDeclaration()) {
const declaration = id.get("declaration");
if (declaration.isDeclaration()) {
search.push(declaration);
}
continue;
}

if (outerOnly) {
if (id.isFunctionDeclaration()) {
search.push(id.get("id"));
continue;
}
if (id.isFunctionExpression()) {
continue;
}
}

if (keys) {
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
let child = id.get(key);
if (Array.isArray(child) || child.node) {
search = search.concat(child);
}
}
}
}

return ids;
}

export function getOuterBindingIdentifierPaths(duplicates?) {
return this.getBindingIdentifierPaths(duplicates, true);
}
60 changes: 60 additions & 0 deletions packages/babel-traverse/test/family.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
let traverse = require("../lib").default;
let assert = require("assert");
let parse = require("babylon").parse;

describe("path/family", function () {
describe("getBindingIdentifiers", function () {
let ast = parse("var a = 1, {b} = c, [d] = e; function f() {}");
let nodes = {}, paths = {}, outerNodes = {}, outerPaths = {};
traverse(ast, {
VariableDeclaration(path) {
nodes = path.getBindingIdentifiers();
paths = path.getBindingIdentifierPaths();
},
FunctionDeclaration(path) {
outerNodes = path.getOuterBindingIdentifiers();
outerPaths = path.getOuterBindingIdentifierPaths();
}
});

it("should contain keys of nodes in paths", function () {
Object.keys(nodes).forEach((id) => {
assert.strictEqual(hop(paths, id), true, "Node's keys exists in paths");
});
});

it("should contain outer bindings", function () {
Object.keys(outerNodes).forEach((id) => {
assert.strictEqual(hop(outerPaths, id), true, "Has same outer keys");
});
});

it("should return paths", function () {
Object.keys(paths).forEach((id) => {
assert.strictEqual(!!paths[id].node, true, "Has a property node that's not falsy");
assert.strictEqual(paths[id].type, paths[id].node.type, "type matches");
});

Object.keys(outerPaths).forEach((id) => {
assert.strictEqual(!!outerPaths[id].node, true, "has property node");
assert.strictEqual(outerPaths[id].type, outerPaths[id].node.type, "type matches");
});
});

it("should match paths and nodes returned for the same ast", function () {
Object.keys(nodes).forEach((id) => {
assert.strictEqual(nodes[id], paths[id].node, "Nodes match");
});
});

it("should match paths and nodes returned for outer Bindings", function () {
Object.keys(outerNodes).forEach((id) => {
assert.strictEqual(outerNodes[id], outerPaths[id].node, "nodes match");
});
});
});
});

function hop(o, key) {
return Object.hasOwnProperty.call(o, key);
}

0 comments on commit 95f2048

Please sign in to comment.