Path: blob/master/node_modules/acorn-walk/dist/walk.mjs
1126 views
// AST walker module for Mozilla Parser API compatible trees12// A simple walk is one where you simply specify callbacks to be3// called on specific nodes. The last two arguments are optional. A4// simple use would be5//6// walk.simple(myTree, {7// Expression: function(node) { ... }8// });9//10// to do something with all expressions. All Parser API node types11// can be used to identify node types, as well as Expression and12// Statement, which denote categories of nodes.13//14// The base argument can be used to pass a custom (recursive)15// walker, and state can be used to give this walked an initial16// state.1718function simple(node, visitors, baseVisitor, state, override) {19if (!baseVisitor) { baseVisitor = base20; }(function c(node, st, override) {21var type = override || node.type, found = visitors[type];22baseVisitor[type](node, st, c);23if (found) { found(node, st); }24})(node, state, override);25}2627// An ancestor walk keeps an array of ancestor nodes (including the28// current node) and passes them to the callback as third parameter29// (and also as state parameter when no other state is present).30function ancestor(node, visitors, baseVisitor, state, override) {31var ancestors = [];32if (!baseVisitor) { baseVisitor = base33; }(function c(node, st, override) {34var type = override || node.type, found = visitors[type];35var isNew = node !== ancestors[ancestors.length - 1];36if (isNew) { ancestors.push(node); }37baseVisitor[type](node, st, c);38if (found) { found(node, st || ancestors, ancestors); }39if (isNew) { ancestors.pop(); }40})(node, state, override);41}4243// A recursive walk is one where your functions override the default44// walkers. They can modify and replace the state parameter that's45// threaded through the walk, and can opt how and whether to walk46// their child nodes (by calling their third argument on these47// nodes).48function recursive(node, state, funcs, baseVisitor, override) {49var visitor = funcs ? make(funcs, baseVisitor || undefined) : baseVisitor50;(function c(node, st, override) {51visitor[override || node.type](node, st, c);52})(node, state, override);53}5455function makeTest(test) {56if (typeof test === "string")57{ return function (type) { return type === test; } }58else if (!test)59{ return function () { return true; } }60else61{ return test }62}6364var Found = function Found(node, state) { this.node = node; this.state = state; };6566// A full walk triggers the callback on each node67function full(node, callback, baseVisitor, state, override) {68if (!baseVisitor) { baseVisitor = base69; }(function c(node, st, override) {70var type = override || node.type;71baseVisitor[type](node, st, c);72if (!override) { callback(node, st, type); }73})(node, state, override);74}7576// An fullAncestor walk is like an ancestor walk, but triggers77// the callback on each node78function fullAncestor(node, callback, baseVisitor, state) {79if (!baseVisitor) { baseVisitor = base; }80var ancestors = []81;(function c(node, st, override) {82var type = override || node.type;83var isNew = node !== ancestors[ancestors.length - 1];84if (isNew) { ancestors.push(node); }85baseVisitor[type](node, st, c);86if (!override) { callback(node, st || ancestors, ancestors, type); }87if (isNew) { ancestors.pop(); }88})(node, state);89}9091// Find a node with a given start, end, and type (all are optional,92// null can be used as wildcard). Returns a {node, state} object, or93// undefined when it doesn't find a matching node.94function findNodeAt(node, start, end, test, baseVisitor, state) {95if (!baseVisitor) { baseVisitor = base; }96test = makeTest(test);97try {98(function c(node, st, override) {99var type = override || node.type;100if ((start == null || node.start <= start) &&101(end == null || node.end >= end))102{ baseVisitor[type](node, st, c); }103if ((start == null || node.start === start) &&104(end == null || node.end === end) &&105test(type, node))106{ throw new Found(node, st) }107})(node, state);108} catch (e) {109if (e instanceof Found) { return e }110throw e111}112}113114// Find the innermost node of a given type that contains the given115// position. Interface similar to findNodeAt.116function findNodeAround(node, pos, test, baseVisitor, state) {117test = makeTest(test);118if (!baseVisitor) { baseVisitor = base; }119try {120(function c(node, st, override) {121var type = override || node.type;122if (node.start > pos || node.end < pos) { return }123baseVisitor[type](node, st, c);124if (test(type, node)) { throw new Found(node, st) }125})(node, state);126} catch (e) {127if (e instanceof Found) { return e }128throw e129}130}131132// Find the outermost matching node after a given position.133function findNodeAfter(node, pos, test, baseVisitor, state) {134test = makeTest(test);135if (!baseVisitor) { baseVisitor = base; }136try {137(function c(node, st, override) {138if (node.end < pos) { return }139var type = override || node.type;140if (node.start >= pos && test(type, node)) { throw new Found(node, st) }141baseVisitor[type](node, st, c);142})(node, state);143} catch (e) {144if (e instanceof Found) { return e }145throw e146}147}148149// Find the outermost matching node before a given position.150function findNodeBefore(node, pos, test, baseVisitor, state) {151test = makeTest(test);152if (!baseVisitor) { baseVisitor = base; }153var max154;(function c(node, st, override) {155if (node.start > pos) { return }156var type = override || node.type;157if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node))158{ max = new Found(node, st); }159baseVisitor[type](node, st, c);160})(node, state);161return max162}163164// Fallback to an Object.create polyfill for older environments.165var create = Object.create || function(proto) {166function Ctor() {}167Ctor.prototype = proto;168return new Ctor169};170171// Used to create a custom walker. Will fill in all missing node172// type properties with the defaults.173function make(funcs, baseVisitor) {174var visitor = create(baseVisitor || base);175for (var type in funcs) { visitor[type] = funcs[type]; }176return visitor177}178179function skipThrough(node, st, c) { c(node, st); }180function ignore(_node, _st, _c) {}181182// Node walkers.183184var base = {};185186base.Program = base.BlockStatement = function (node, st, c) {187for (var i = 0, list = node.body; i < list.length; i += 1)188{189var stmt = list[i];190191c(stmt, st, "Statement");192}193};194base.Statement = skipThrough;195base.EmptyStatement = ignore;196base.ExpressionStatement = base.ParenthesizedExpression = base.ChainExpression =197function (node, st, c) { return c(node.expression, st, "Expression"); };198base.IfStatement = function (node, st, c) {199c(node.test, st, "Expression");200c(node.consequent, st, "Statement");201if (node.alternate) { c(node.alternate, st, "Statement"); }202};203base.LabeledStatement = function (node, st, c) { return c(node.body, st, "Statement"); };204base.BreakStatement = base.ContinueStatement = ignore;205base.WithStatement = function (node, st, c) {206c(node.object, st, "Expression");207c(node.body, st, "Statement");208};209base.SwitchStatement = function (node, st, c) {210c(node.discriminant, st, "Expression");211for (var i$1 = 0, list$1 = node.cases; i$1 < list$1.length; i$1 += 1) {212var cs = list$1[i$1];213214if (cs.test) { c(cs.test, st, "Expression"); }215for (var i = 0, list = cs.consequent; i < list.length; i += 1)216{217var cons = list[i];218219c(cons, st, "Statement");220}221}222};223base.SwitchCase = function (node, st, c) {224if (node.test) { c(node.test, st, "Expression"); }225for (var i = 0, list = node.consequent; i < list.length; i += 1)226{227var cons = list[i];228229c(cons, st, "Statement");230}231};232base.ReturnStatement = base.YieldExpression = base.AwaitExpression = function (node, st, c) {233if (node.argument) { c(node.argument, st, "Expression"); }234};235base.ThrowStatement = base.SpreadElement =236function (node, st, c) { return c(node.argument, st, "Expression"); };237base.TryStatement = function (node, st, c) {238c(node.block, st, "Statement");239if (node.handler) { c(node.handler, st); }240if (node.finalizer) { c(node.finalizer, st, "Statement"); }241};242base.CatchClause = function (node, st, c) {243if (node.param) { c(node.param, st, "Pattern"); }244c(node.body, st, "Statement");245};246base.WhileStatement = base.DoWhileStatement = function (node, st, c) {247c(node.test, st, "Expression");248c(node.body, st, "Statement");249};250base.ForStatement = function (node, st, c) {251if (node.init) { c(node.init, st, "ForInit"); }252if (node.test) { c(node.test, st, "Expression"); }253if (node.update) { c(node.update, st, "Expression"); }254c(node.body, st, "Statement");255};256base.ForInStatement = base.ForOfStatement = function (node, st, c) {257c(node.left, st, "ForInit");258c(node.right, st, "Expression");259c(node.body, st, "Statement");260};261base.ForInit = function (node, st, c) {262if (node.type === "VariableDeclaration") { c(node, st); }263else { c(node, st, "Expression"); }264};265base.DebuggerStatement = ignore;266267base.FunctionDeclaration = function (node, st, c) { return c(node, st, "Function"); };268base.VariableDeclaration = function (node, st, c) {269for (var i = 0, list = node.declarations; i < list.length; i += 1)270{271var decl = list[i];272273c(decl, st);274}275};276base.VariableDeclarator = function (node, st, c) {277c(node.id, st, "Pattern");278if (node.init) { c(node.init, st, "Expression"); }279};280281base.Function = function (node, st, c) {282if (node.id) { c(node.id, st, "Pattern"); }283for (var i = 0, list = node.params; i < list.length; i += 1)284{285var param = list[i];286287c(param, st, "Pattern");288}289c(node.body, st, node.expression ? "Expression" : "Statement");290};291292base.Pattern = function (node, st, c) {293if (node.type === "Identifier")294{ c(node, st, "VariablePattern"); }295else if (node.type === "MemberExpression")296{ c(node, st, "MemberPattern"); }297else298{ c(node, st); }299};300base.VariablePattern = ignore;301base.MemberPattern = skipThrough;302base.RestElement = function (node, st, c) { return c(node.argument, st, "Pattern"); };303base.ArrayPattern = function (node, st, c) {304for (var i = 0, list = node.elements; i < list.length; i += 1) {305var elt = list[i];306307if (elt) { c(elt, st, "Pattern"); }308}309};310base.ObjectPattern = function (node, st, c) {311for (var i = 0, list = node.properties; i < list.length; i += 1) {312var prop = list[i];313314if (prop.type === "Property") {315if (prop.computed) { c(prop.key, st, "Expression"); }316c(prop.value, st, "Pattern");317} else if (prop.type === "RestElement") {318c(prop.argument, st, "Pattern");319}320}321};322323base.Expression = skipThrough;324base.ThisExpression = base.Super = base.MetaProperty = ignore;325base.ArrayExpression = function (node, st, c) {326for (var i = 0, list = node.elements; i < list.length; i += 1) {327var elt = list[i];328329if (elt) { c(elt, st, "Expression"); }330}331};332base.ObjectExpression = function (node, st, c) {333for (var i = 0, list = node.properties; i < list.length; i += 1)334{335var prop = list[i];336337c(prop, st);338}339};340base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration;341base.SequenceExpression = function (node, st, c) {342for (var i = 0, list = node.expressions; i < list.length; i += 1)343{344var expr = list[i];345346c(expr, st, "Expression");347}348};349base.TemplateLiteral = function (node, st, c) {350for (var i = 0, list = node.quasis; i < list.length; i += 1)351{352var quasi = list[i];353354c(quasi, st);355}356357for (var i$1 = 0, list$1 = node.expressions; i$1 < list$1.length; i$1 += 1)358{359var expr = list$1[i$1];360361c(expr, st, "Expression");362}363};364base.TemplateElement = ignore;365base.UnaryExpression = base.UpdateExpression = function (node, st, c) {366c(node.argument, st, "Expression");367};368base.BinaryExpression = base.LogicalExpression = function (node, st, c) {369c(node.left, st, "Expression");370c(node.right, st, "Expression");371};372base.AssignmentExpression = base.AssignmentPattern = function (node, st, c) {373c(node.left, st, "Pattern");374c(node.right, st, "Expression");375};376base.ConditionalExpression = function (node, st, c) {377c(node.test, st, "Expression");378c(node.consequent, st, "Expression");379c(node.alternate, st, "Expression");380};381base.NewExpression = base.CallExpression = function (node, st, c) {382c(node.callee, st, "Expression");383if (node.arguments)384{ for (var i = 0, list = node.arguments; i < list.length; i += 1)385{386var arg = list[i];387388c(arg, st, "Expression");389} }390};391base.MemberExpression = function (node, st, c) {392c(node.object, st, "Expression");393if (node.computed) { c(node.property, st, "Expression"); }394};395base.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (node, st, c) {396if (node.declaration)397{ c(node.declaration, st, node.type === "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression"); }398if (node.source) { c(node.source, st, "Expression"); }399};400base.ExportAllDeclaration = function (node, st, c) {401if (node.exported)402{ c(node.exported, st); }403c(node.source, st, "Expression");404};405base.ImportDeclaration = function (node, st, c) {406for (var i = 0, list = node.specifiers; i < list.length; i += 1)407{408var spec = list[i];409410c(spec, st);411}412c(node.source, st, "Expression");413};414base.ImportExpression = function (node, st, c) {415c(node.source, st, "Expression");416};417base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.Literal = ignore;418419base.TaggedTemplateExpression = function (node, st, c) {420c(node.tag, st, "Expression");421c(node.quasi, st, "Expression");422};423base.ClassDeclaration = base.ClassExpression = function (node, st, c) { return c(node, st, "Class"); };424base.Class = function (node, st, c) {425if (node.id) { c(node.id, st, "Pattern"); }426if (node.superClass) { c(node.superClass, st, "Expression"); }427c(node.body, st);428};429base.ClassBody = function (node, st, c) {430for (var i = 0, list = node.body; i < list.length; i += 1)431{432var elt = list[i];433434c(elt, st);435}436};437base.MethodDefinition = base.Property = function (node, st, c) {438if (node.computed) { c(node.key, st, "Expression"); }439c(node.value, st, "Expression");440};441442export { ancestor, base, findNodeAfter, findNodeAround, findNodeAt, findNodeBefore, full, fullAncestor, make, recursive, simple };443444445