react / wstein / node_modules / browserify / node_modules / syntax-error / node_modules / acorn / src / walk / index.js
80555 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,12// Statement, and ScopeBody, 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.1718export function simple(node, visitors, base, state) {19if (!base) base = exports.base20;(function c(node, st, override) {21let type = override || node.type, found = visitors[type]22base[type](node, st, c)23if (found) found(node, st)24})(node, state)25}2627// An ancestor walk builds up an array of ancestor nodes (including28// the current node) and passes them to the callback as the state parameter.29export function ancestor(node, visitors, base, state) {30if (!base) base = exports.base31if (!state) state = []32;(function c(node, st, override) {33let type = override || node.type, found = visitors[type]34if (node != st[st.length - 1]) {35st = st.slice()36st.push(node)37}38base[type](node, st, c)39if (found) found(node, st)40})(node, state)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).48export function recursive(node, state, funcs, base) {49let visitor = funcs ? exports.make(funcs, base) : base50;(function c(node, st, override) {51visitor[override || node.type](node, st, c)52})(node, state)53}5455function makeTest(test) {56if (typeof test == "string")57return type => type == test58else if (!test)59return () => true60else61return test62}6364class Found {65constructor(node, state) { this.node = node; this.state = state }66}6768// Find a node with a given start, end, and type (all are optional,69// null can be used as wildcard). Returns a {node, state} object, or70// undefined when it doesn't find a matching node.71export function findNodeAt(node, start, end, test, base, state) {72test = makeTest(test)73if (!base) base = exports.base74try {75;(function c(node, st, override) {76let type = override || node.type77if ((start == null || node.start <= start) &&78(end == null || node.end >= end))79base[type](node, st, c)80if (test(type, node) &&81(start == null || node.start == start) &&82(end == null || node.end == end))83throw new Found(node, st)84})(node, state)85} catch (e) {86if (e instanceof Found) return e87throw e88}89}9091// Find the innermost node of a given type that contains the given92// position. Interface similar to findNodeAt.93export function findNodeAround(node, pos, test, base, state) {94test = makeTest(test)95if (!base) base = exports.base96try {97;(function c(node, st, override) {98let type = override || node.type99if (node.start > pos || node.end < pos) return100base[type](node, st, c)101if (test(type, node)) throw new Found(node, st)102})(node, state)103} catch (e) {104if (e instanceof Found) return e105throw e106}107}108109// Find the outermost matching node after a given position.110export function findNodeAfter(node, pos, test, base, state) {111test = makeTest(test)112if (!base) base = exports.base113try {114;(function c(node, st, override) {115if (node.end < pos) return116let type = override || node.type117if (node.start >= pos && test(type, node)) throw new Found(node, st)118base[type](node, st, c)119})(node, state)120} catch (e) {121if (e instanceof Found) return e122throw e123}124}125126// Find the outermost matching node before a given position.127export function findNodeBefore(node, pos, test, base, state) {128test = makeTest(test)129if (!base) base = exports.base130let max131;(function c(node, st, override) {132if (node.start > pos) return133let type = override || node.type134if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node))135max = new Found(node, st)136base[type](node, st, c)137})(node, state)138return max139}140141// Used to create a custom walker. Will fill in all missing node142// type properties with the defaults.143export function make(funcs, base) {144if (!base) base = exports.base145let visitor = {}146for (var type in base) visitor[type] = base[type]147for (var type in funcs) visitor[type] = funcs[type]148return visitor149}150151function skipThrough(node, st, c) { c(node, st) }152function ignore(_node, _st, _c) {}153154// Node walkers.155156export const base = {}157158base.Program = base.BlockStatement = (node, st, c) => {159for (let i = 0; i < node.body.length; ++i)160c(node.body[i], st, "Statement")161}162base.Statement = skipThrough163base.EmptyStatement = ignore164base.ExpressionStatement = base.ParenthesizedExpression =165(node, st, c) => c(node.expression, st, "Expression")166base.IfStatement = (node, st, c) => {167c(node.test, st, "Expression")168c(node.consequent, st, "Statement")169if (node.alternate) c(node.alternate, st, "Statement")170}171base.LabeledStatement = (node, st, c) => c(node.body, st, "Statement")172base.BreakStatement = base.ContinueStatement = ignore173base.WithStatement = (node, st, c) => {174c(node.object, st, "Expression")175c(node.body, st, "Statement")176}177base.SwitchStatement = (node, st, c) => {178c(node.discriminant, st, "Expression")179for (let i = 0; i < node.cases.length; ++i) {180let cs = node.cases[i]181if (cs.test) c(cs.test, st, "Expression")182for (let j = 0; j < cs.consequent.length; ++j)183c(cs.consequent[j], st, "Statement")184}185}186base.ReturnStatement = base.YieldExpression = (node, st, c) => {187if (node.argument) c(node.argument, st, "Expression")188}189base.ThrowStatement = base.SpreadElement = base.RestElement =190(node, st, c) => c(node.argument, st, "Expression")191base.TryStatement = (node, st, c) => {192c(node.block, st, "Statement")193if (node.handler) c(node.handler.body, st, "ScopeBody")194if (node.finalizer) c(node.finalizer, st, "Statement")195}196base.WhileStatement = base.DoWhileStatement = (node, st, c) => {197c(node.test, st, "Expression")198c(node.body, st, "Statement")199}200base.ForStatement = (node, st, c) => {201if (node.init) c(node.init, st, "ForInit")202if (node.test) c(node.test, st, "Expression")203if (node.update) c(node.update, st, "Expression")204c(node.body, st, "Statement")205}206base.ForInStatement = base.ForOfStatement = (node, st, c) => {207c(node.left, st, "ForInit")208c(node.right, st, "Expression")209c(node.body, st, "Statement")210}211base.ForInit = (node, st, c) => {212if (node.type == "VariableDeclaration") c(node, st)213else c(node, st, "Expression")214}215base.DebuggerStatement = ignore216217base.FunctionDeclaration = (node, st, c) => c(node, st, "Function")218base.VariableDeclaration = (node, st, c) => {219for (let i = 0; i < node.declarations.length; ++i) {220let decl = node.declarations[i]221if (decl.init) c(decl.init, st, "Expression")222}223}224225base.Function = (node, st, c) => c(node.body, st, "ScopeBody")226base.ScopeBody = (node, st, c) => c(node, st, "Statement")227228base.Expression = skipThrough229base.ThisExpression = base.Super = base.MetaProperty = ignore230base.ArrayExpression = base.ArrayPattern = (node, st, c) => {231for (let i = 0; i < node.elements.length; ++i) {232let elt = node.elements[i]233if (elt) c(elt, st, "Expression")234}235}236base.ObjectExpression = base.ObjectPattern = (node, st, c) => {237for (let i = 0; i < node.properties.length; ++i)238c(node.properties[i], st)239}240base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration241base.SequenceExpression = base.TemplateLiteral = (node, st, c) => {242for (let i = 0; i < node.expressions.length; ++i)243c(node.expressions[i], st, "Expression")244}245base.UnaryExpression = base.UpdateExpression = (node, st, c) => {246c(node.argument, st, "Expression")247}248base.BinaryExpression = base.AssignmentExpression = base.AssignmentPattern = base.LogicalExpression = (node, st, c) => {249c(node.left, st, "Expression")250c(node.right, st, "Expression")251}252base.ConditionalExpression = (node, st, c) => {253c(node.test, st, "Expression")254c(node.consequent, st, "Expression")255c(node.alternate, st, "Expression")256}257base.NewExpression = base.CallExpression = (node, st, c) => {258c(node.callee, st, "Expression")259if (node.arguments) for (let i = 0; i < node.arguments.length; ++i)260c(node.arguments[i], st, "Expression")261}262base.MemberExpression = (node, st, c) => {263c(node.object, st, "Expression")264if (node.computed) c(node.property, st, "Expression")265}266base.ExportNamedDeclaration = base.ExportDefaultDeclaration = (node, st, c) => c(node.declaration, st)267base.ImportDeclaration = (node, st, c) => {268for (let i = 0; i < node.specifiers.length; i++)269c(node.specifiers[i], st)270}271base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.Literal = ignore272273base.TaggedTemplateExpression = (node, st, c) => {274c(node.tag, st, "Expression")275c(node.quasi, st)276}277base.ClassDeclaration = base.ClassExpression = (node, st, c) => {278if (node.superClass) c(node.superClass, st, "Expression")279for (let i = 0; i < node.body.body.length; i++)280c(node.body.body[i], st)281}282base.MethodDefinition = base.Property = (node, st, c) => {283if (node.computed) c(node.key, st, "Expression")284c(node.value, st, "Expression")285}286base.ComprehensionExpression = (node, st, c) => {287for (let i = 0; i < node.blocks.length; i++)288c(node.blocks[i].right, st, "Expression")289c(node.body, st, "Expression")290}291292293