move visitor-keys from traverse to types

This commit is contained in:
Sebastian McKenzie
2014-11-04 12:47:27 +11:00
parent 6519ceaa63
commit 9ef826b53e
3 changed files with 63 additions and 13 deletions

View File

@@ -1,23 +1,30 @@
var _ = require("lodash");
module.exports = traverse;
var traverse = module.exports = function (parent, callbacks, blacklistTypes) {
var Scope = require("./scope");
var t = require("./types");
var _ = require("lodash");
function traverse(parent, callbacks, opts) {
// falsy node
if (!parent) return;
// array of nodes
if (_.isArray(parent)) {
_.each(parent, function (node) {
traverse(node, callbacks, blacklistTypes);
traverse(node, callbacks, opts);
});
return;
}
// unknown node type to traverse
var keys = traverse.VISITOR_KEYS[parent.type];
var keys = t.VISITOR_KEYS[parent.type];
if (!keys) return;
opts = opts || {};
if (_.isArray(opts)) opts = { blacklist: opts };
// blacklist these node types from being traversed
blacklistTypes = blacklistTypes || [];
var blacklistTypes = opts.blacklist || [];
// normalise callbacks
if (_.isFunction(callbacks)) callbacks = { enter: callbacks };
@@ -37,12 +44,13 @@ var traverse = module.exports = function (parent, callbacks, blacklistTypes) {
// replace node
var maybeReplace = function (result) {
if (result === false) return;
if (result != null) node = obj[key] = result;
};
// enter
if (callbacks.enter) {
result = callbacks.enter(node, parent, obj, key);
result = callbacks.enter(node, parent, opts);
// stop iteration
if (result === false) return;
@@ -51,11 +59,13 @@ var traverse = module.exports = function (parent, callbacks, blacklistTypes) {
}
// traverse node
traverse(node, callbacks, blacklistTypes);
var opts2 = _.clone(opts);
if (t.isScope(node)) opts2.scope = new Scope(opts.scope, node);
traverse(node, callbacks, opts2);
// exit
if (callbacks.exit) {
maybeReplace(callbacks.exit(node, parent, obj, key));
maybeReplace(callbacks.exit(node, parent, opts));
}
};
@@ -71,8 +81,6 @@ var traverse = module.exports = function (parent, callbacks, blacklistTypes) {
});
};
traverse.VISITOR_KEYS = require("./visitor-keys");
traverse.removeProperties = function (tree) {
var clear = function (node) {
delete node.tokens;
@@ -121,7 +129,7 @@ traverse.hasType = function (tree, type, blacklistTypes) {
has = true;
return false;
}
}, blacklistTypes);
}, { blacklist: blacklistTypes });
}
return has;

View File

@@ -6,7 +6,9 @@ var t = exports;
//
_.each(traverse.VISITOR_KEYS, function (keys, type) {
t.VISITOR_KEYS = require("./visitor-keys");
_.each(t.VISITOR_KEYS, function (keys, type) {
t["is" + type] = function (node) {
return node && node.type === type;
};
@@ -14,7 +16,7 @@ _.each(traverse.VISITOR_KEYS, function (keys, type) {
//
t.BUILDER_KEYS = _.defaults(require("./builder-keys"), traverse.VISITOR_KEYS);
t.BUILDER_KEYS = _.defaults(require("./builder-keys"), t.VISITOR_KEYS);
_.each(t.BUILDER_KEYS, function (keys, type) {
t[type[0].toLowerCase() + type.slice(1)] = function () {
@@ -92,6 +94,37 @@ t.toBlock = function (node, parent) {
return t.blockStatement(node);
};
t.getIds = function (node) {
var search = [node];
var ids = [];
while (search.length) {
var id = search.shift();
if (t.isIdentifier(id)) {
ids.push(id.name);
} else if (t.isArrayPattern(id)) {
_.each(id.elements, function (elem) {
search.push(elem);
});
} else if (t.isAssignmentExpression(id)) {
search.push(id.left);
} else if (t.isObjectPattern(id)) {
_.each(id.properties, function (prop) {
search.push(prop.value);
});
} else if (t.isVariableDeclaration(id)) {
search = search.concat(id.declarations);
} else if (t.isVariableDeclarator(id)) {
search.push(id.id);
} else {
throw new Error("unknown node " + id.type);
}
}
return ids;
};
t.inherits = function (child, parent) {
child.loc = parent.loc;
child.end = parent.end;
@@ -119,6 +152,10 @@ t.needsWhitespace = function (node, expression) {
return true;
}
if (t.isCallExpression(node) && t.isFunction(node.callee)) {
return true;
}
if (expression) return false;
//
@@ -192,6 +229,11 @@ t.needsParans = function (node, parent) {
}
}
// (class {});
if (t.isClassExpression(node) && t.isExpressionStatement(parent)) {
return true;
}
if (t.isSequenceExpression(node)) {
if (t.isForStatement(parent)) {
// Although parentheses wouldn't hurt around sequence