Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

Commit

Permalink
Use estraverse in tree-iterator.
Browse files Browse the repository at this point in the history
  • Loading branch information
mdevils committed Dec 5, 2014
1 parent c461073 commit 573e278
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 101 deletions.
45 changes: 20 additions & 25 deletions lib/js-file.js
Expand Up @@ -26,25 +26,22 @@ var JsFile = function(filename, source, tree) {
this._buildTokenIndex();

this.iterate(function(node, parentNode, parentCollection) {
if (node) {
var type = node.type;
if (type) {
node.parentNode = parentNode;
node.parentCollection = parentCollection;
(index[type] || (index[type] = [])).push(node);
var type = node.type;

// Temporary fix (i hope) for esprima tokenizer
// (https://code.google.com/p/esprima/issues/detail?id=481)
// Fixes #83, #180
switch (type) {
case 'Property':
convertKeywordToIdentifierIfRequired(node.key);
break;
case 'MemberExpression':
convertKeywordToIdentifierIfRequired(node.property);
break;
}
}
node.parentNode = parentNode;
node.parentCollection = parentCollection;
(index[type] || (index[type] = [])).push(node);

// Temporary fix (i hope) for esprima tokenizer
// (https://code.google.com/p/esprima/issues/detail?id=481)
// Fixes #83, #180
switch (type) {
case 'Property':
convertKeywordToIdentifierIfRequired(node.key);
break;
case 'MemberExpression':
convertKeywordToIdentifierIfRequired(node.property);
break;
}
});

Expand Down Expand Up @@ -285,13 +282,11 @@ JsFile.prototype = {
getNodeByRange: function(number) {
var result = {};
this.iterate(function(node) {
if (node && node.range) {
if (number > node.range[0] && number < node.range[1]) {
result = node;
}
if (number < node.range[0]) {
return false;
}
if (number > node.range[0] && number < node.range[1]) {
result = node;
}
if (number < node.range[0]) {
return false;
}
});
return result;
Expand Down
6 changes: 3 additions & 3 deletions lib/rules/require-multiple-var-decl.js
Expand Up @@ -22,11 +22,11 @@ function onevar(file, errors) {
var firstParent = true;

file.iterate(function(node) {
var type = node && node.type;
var kind = node && node.kind;
var type = node.type;
var kind = node.kind;

// Don't go in nested scopes
if (!firstParent && type && ['FunctionDeclaration', 'FunctionExpression'].indexOf(type) > -1) {
if (!firstParent && ['FunctionDeclaration', 'FunctionExpression'].indexOf(type) > -1) {
return false;
}

Expand Down
99 changes: 26 additions & 73 deletions lib/tree-iterator.js
@@ -1,83 +1,36 @@
var estraverse = require('estraverse');

module.exports = {
iterate: iterate
};

var iterableProperties = {
'body': true,
'expression': true,

// if
'test': true,
'consequent': true,
'alternate': true,

'object': true,

//switch
'discriminant': true,
'cases': true,

// return
'argument': true,
'arguments': true,

// try
'block': true,
'guardedHandlers': true,
'handlers': true,
'finalizer': true,

// catch
'handler': true,

// for
'init': true,
'update': true,

// for in
'left': true,
'right': true,

// var
'declarations': true,

// array
'elements': true,

// object
'properties': true,
'key': true,
'value': true,

// new
'callee': true,

// export (ES6)
'declaration': true,

// xxx.yyy
'property': true
};

function iterate(node, cb, parentNode, parentCollection) {
if (cb(node, parentNode, parentCollection) === false) {
return;
}

for (var propName in node) {
if (node.hasOwnProperty(propName)) {
if (iterableProperties[propName]) {
var contents = node[propName];
if (typeof contents === 'object') {
if (Array.isArray(contents)) {
for (var i = 0, l = contents.length; i < l; i++) {
iterate(contents[i], cb, node, contents);
function iterate(node, cb) {
if ('type' in node) {
estraverse.traverse(node, {
enter: function(node, parent) {
var parentCollection = [];

// parentCollection support
var path = this.path();
if (path) {
var collectionKey;
while (path.length > 0) {
var pathElement = path.pop();
if (typeof pathElement === 'string') {
collectionKey = pathElement;
}
} else {
iterate(contents, cb, node, [contents]);
}

parentCollection = parent[collectionKey];
if (!Array.isArray(parentCollection)) {
parentCollection = [parentCollection];
}
}

if (cb(node, parent, parentCollection) === false) {
return estraverse.VisitorOption.Skip;
}
}
}
});
}
}
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -30,6 +30,7 @@
"commander": "~2.5.0",
"esprima": "~1.2.2",
"esprima-harmony-jscs": "1.1.0-dev-harmony",
"estraverse": "~1.8.0",
"exit": "~0.1.2",
"glob": "~4.0.0",
"minimatch": "~1.0.0",
Expand Down
33 changes: 33 additions & 0 deletions test/tree-iterator.js
@@ -0,0 +1,33 @@
var assert = require('assert');
var esprima = require('esprima');
var sinon = require('sinon');
var iterate = require('../lib/tree-iterator').iterate;

describe('modules/tree-iterator', function() {

it('should pass parent and parentCollection', function() {
var spy = sinon.spy();
iterate(esprima.parse('1;', {loc: true, range: true, comment: true, tokens: true}), spy);
assert.equal(spy.callCount, 3);
assert.equal(spy.getCall(0).args[0].type, 'Program');
assert.equal(spy.getCall(0).args[1], null);
assert.equal(spy.getCall(1).args[0].type, 'ExpressionStatement');
assert.equal(spy.getCall(2).args[0].type, 'Literal');
});

it('should not fail for empty object', function() {
var spy = sinon.spy();
iterate({}, spy);
assert.equal(spy.callCount, 0);
});

it('should exit thread on false result', function() {
var spy = sinon.spy(function() {
return false;
});
iterate(esprima.parse('1;', {loc: true, range: true, comment: true, tokens: true}), spy);
assert.equal(spy.callCount, 1);
assert.equal(spy.getCall(0).args[0].type, 'Program');
});

});

0 comments on commit 573e278

Please sign in to comment.