automatically explode visitors

This commit is contained in:
Sebastian McKenzie
2015-05-09 00:07:08 +01:00
parent c60ad89937
commit e037ae7bc9
8 changed files with 25 additions and 24 deletions

View File

@@ -26,7 +26,6 @@ export const MESSAGES = {
traverseNeedsParent: "Must pass a scope and parentPath unless traversing a Program/File got a $1 node",
traverseVerifyRootFunction: "You passed `traverse()` a function when it expected a visitor object, are you sure you didn't mean `{ enter: Function }`?",
traverseVerifyVisitorFunction: "You passed \`traverse()\` a visitor object with the key $1 that's a `Function` instead of `{ enter: Function }`. You need to normalise your visitor with `traverse.explode(visitor)`.",
traverseVerifyVisitorProperty: "You passed `traverse()` a visitor object with the property $1 that has the invalid property $2",
traverseVerifyNodeType: "You gave us a visitor for the node type $1 but it's not a valid type",

View File

@@ -5,7 +5,7 @@ import object from "../../helpers/object";
import * as util from "../../util";
import * as t from "../../types";
var remapVisitor = traverse.explode({
var remapVisitor = {
enter(node, parent, scope, formatter) {
if (node._skipModulesRemap) {
return this.skip();
@@ -63,7 +63,7 @@ var remapVisitor = traverse.explode({
return t.sequenceExpression(nodes);
}
});
};
var importsVisitor = {
ImportDeclaration: {
@@ -74,7 +74,7 @@ var importsVisitor = {
}
};
var exportsVisitor = traverse.explode({
var exportsVisitor = {
ExportDeclaration: {
enter(node, parent, scope, formatter) {
formatter.hasLocalExports = true;
@@ -106,7 +106,7 @@ var exportsVisitor = traverse.explode({
}
}
}
});
};
export default class DefaultFormatter {
constructor(file) {

View File

@@ -35,7 +35,7 @@ var collectPropertyReferencesVisitor = {
}
};
var constructorVisitor = traverse.explode({
var constructorVisitor = {
ThisExpression: {
enter(node, parent, scope, ref) {
return ref;
@@ -49,9 +49,9 @@ var constructorVisitor = traverse.explode({
}
}
}
});
};
var verifyConstructorVisitor = traverse.explode({
var verifyConstructorVisitor = {
MethodDefinition: {
enter() {
this.skip();
@@ -96,7 +96,7 @@ var verifyConstructorVisitor = traverse.explode({
}
}
}
});
};
class ClassTransformer {

View File

@@ -10,7 +10,7 @@ var hasDefaults = function (node) {
return false;
};
var iifeVisitor = traverse.explode({
var iifeVisitor = {
ReferencedIdentifier(node, parent, scope, state) {
if (!state.scope.hasOwnBinding(node.name)) return;
if (state.scope.bindingIdentifierEquals(node.name, node)) return;
@@ -18,7 +18,7 @@ var iifeVisitor = traverse.explode({
state.iife = true;
this.stop();
}
});
};
exports.Function = function (node, parent, scope, file) {
if (!hasDefaults(node)) return;

View File

@@ -1,7 +1,7 @@
import traverse from "../../../traversal";
import * as t from "../../../types";
var visitor = traverse.explode({
var visitor = {
ReferencedIdentifier(node, parent, scope, state) {
if (t.isFor(parent) && parent.left === node) return;
@@ -25,7 +25,7 @@ var visitor = traverse.explode({
return t.logicalExpression("&&", assert, node);
}
}
});
};
export var metadata = {
optional: true,

View File

@@ -21,7 +21,7 @@ function returnBlock(expr) {
}
// looks for and replaces tail recursion calls
var firstPass = traverse.explode({
var firstPass = {
enter(node, parent, scope, state) {
if (t.isTryStatement(parent)) {
if (node === parent.block) {
@@ -45,11 +45,11 @@ var firstPass = traverse.explode({
this.skip();
state.vars.push(node);
}
});
};
// hoists up function declarations, replaces `this` and `arguments` and marks
// them as needed
var secondPass = traverse.explode({
var secondPass = {
ThisExpression(node, parent, scope, state) {
state.needsThis = true;
return state.getThisId();
@@ -71,10 +71,10 @@ var secondPass = traverse.explode({
return node;
}
}
});
};
// optimizes recursion by removing `this` and `arguments` if they aren't used
var thirdPass = traverse.explode({
var thirdPass = {
ExpressionStatement(node, parent, scope, state) {
var expr = node.expression;
if (!t.isAssignmentExpression(expr)) return;
@@ -87,7 +87,7 @@ var thirdPass = traverse.explode({
});
}
}
});
};
class TailCallTransformer {
constructor(path, scope, file) {

View File

@@ -14,7 +14,9 @@ export default function traverse(parent, opts, scope, state, parentPath) {
}
if (!opts) opts = {};
visitors.verify(opts);
visitors.explode(opts);
// array of nodes
if (Array.isArray(parent)) {

View File

@@ -4,6 +4,9 @@ import * as t from "../types";
import esquery from "esquery";
export function explode(visitor, mergeConflicts) {
if (visitor._exploded) return visitor;
visitor._exploded = true;
// make sure there's no __esModule type since this is because we're using loose mode
// and it sets __esModule to be enumerable on all modules :(
delete visitor.__esModule;
@@ -86,15 +89,12 @@ export function verify(visitor) {
for (var nodeType in visitor) {
if (shouldIgnoreKey(nodeType)) continue;
if (t.TYPES.indexOf(nodeType) < 0) {
if (t.TYPES.indexOf(nodeType) < 0 && !virtualTypes[nodeType]) {
throw new Error(messages.get("traverseVerifyNodeType", nodeType));
}
var visitors = visitor[nodeType];
if (typeof visitors === "function") {
throw new Error(messages.get("traverseVerifyVisitorFunction", nodeType));
} else if (typeof visitors === "object") {
if (typeof visitors === "object") {
for (var visitorKey in visitors) {
if (visitorKey === "enter" || visitorKey === "exit") continue;
throw new Error(messages.get("traverseVerifyVisitorProperty", nodeType, visitorKey));