Skip to content

Commit

Permalink
Initial
Browse files Browse the repository at this point in the history
  • Loading branch information
mrjoelkemp committed Mar 18, 2014
0 parents commit 2384f0d
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
46 changes: 46 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
Execute a callback on every node of a source code's AST and
stop walking whenever you see fit.

*A variation of [substack/node-detective](https://github.com/substack/node-detective)
and simplification of [substack/node-falafel](https://github.com/substack/node-falafel).*

`npm install node-source-walk`

### Usage

```javascript
var Walker = require('node-source-walk');

var walker = new Walker();

// Assume src is the string contents of myfile.js

walker.walk(src, function (node) {
// Example: looking for the use of define()
var callee = node.callee;

if (callee &&
node.type === 'CallExpression' &&
callee.type === 'Identifier' &&
callee.name === 'define') {
console.log('AMD syntax');

// No need to keep traversing since we found
// what we wanted
walker.stopWalking();
}
});

```

### Public Members

`walk(src, cb)`

* Generates and recursively walks through the AST for `src` and executes `cb`
on every node.

`stopWalking()`

* Halts further walking of the AST until another manual call of `walk`.
* This is super-beneficial when dealing with large source files
50 changes: 50 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
var esprima = require('esprima');

module.exports = function () {
// We use global state to stop the recursive
// traversal of the AST
this.shouldStop = false;
};

// Adapted from node-detective
function traverse (node, cb) {
var that = this;

if (this.shouldStop) return;

if (Array.isArray(node)) {
node.forEach(function (x) {
if(x != null) {
// Mark that the node has been visited
x.parent = node;
traverse.call(that, x, cb);
}
});

} else if (node && typeof node === 'object') {
cb(node);

Object.keys(node).forEach(function (key) {
// Avoid visited nodes
if (key === 'parent' || ! node[key]) return;

node[key].parent = node;
traverse.call(that, node[key], cb);
});
}
}

// Executes the passed callback for every traversed node of
// the passed in src's ast
module.exports.prototype.walk = function (src, cb) {
this.shouldStop = false;

var ast = esprima.parse(src);

traverse.call(this, ast, cb);
};

// Halts further traversal of the AST
module.exports.prototype.stopWalking = function () {
this.shouldStop = true;
};
26 changes: 26 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "node-source-walk",
"version": "1.0.0",
"description": "Execute a callback on every node of a source code's AST and",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/mrjoelkemp/node-source-walk"
},
"keywords": [
"ast",
"traversal"
],
"author": "Joel Kemp <joel@mrjoelkemp.com> (http://www.mrjoelkemp.com/)",
"license": "MIT",
"bugs": {
"url": "https://github.com/mrjoelkemp/node-source-walk/issues"
},
"homepage": "https://github.com/mrjoelkemp/node-source-walk",
"dependencies": {
"esprima": "^1.0.4"
}
}

0 comments on commit 2384f0d

Please sign in to comment.