walk.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  3. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  4. (factory((global.acorn = global.acorn || {}, global.acorn.walk = global.acorn.walk || {})));
  5. }(this, (function (exports) { 'use strict';
  6. // AST walker module for Mozilla Parser API compatible trees
  7. // A simple walk is one where you simply specify callbacks to be
  8. // called on specific nodes. The last two arguments are optional. A
  9. // simple use would be
  10. //
  11. // walk.simple(myTree, {
  12. // Expression: function(node) { ... }
  13. // });
  14. //
  15. // to do something with all expressions. All Parser API node types
  16. // can be used to identify node types, as well as Expression,
  17. // Statement, and ScopeBody, which denote categories of nodes.
  18. //
  19. // The base argument can be used to pass a custom (recursive)
  20. // walker, and state can be used to give this walked an initial
  21. // state.
  22. function simple(node, visitors, base, state, override) {
  23. if (!base) base = exports.base
  24. ;(function c(node, st, override) {
  25. var type = override || node.type, found = visitors[type]
  26. base[type](node, st, c)
  27. if (found) found(node, st)
  28. })(node, state, override)
  29. }
  30. // An ancestor walk keeps an array of ancestor nodes (including the
  31. // current node) and passes them to the callback as third parameter
  32. // (and also as state parameter when no other state is present).
  33. function ancestor(node, visitors, base, state) {
  34. if (!base) base = exports.base
  35. var ancestors = []
  36. ;(function c(node, st, override) {
  37. var type = override || node.type, found = visitors[type]
  38. var isNew = node != ancestors[ancestors.length - 1]
  39. if (isNew) ancestors.push(node)
  40. base[type](node, st, c)
  41. if (found) found(node, st || ancestors, ancestors)
  42. if (isNew) ancestors.pop()
  43. })(node, state)
  44. }
  45. // A recursive walk is one where your functions override the default
  46. // walkers. They can modify and replace the state parameter that's
  47. // threaded through the walk, and can opt how and whether to walk
  48. // their child nodes (by calling their third argument on these
  49. // nodes).
  50. function recursive(node, state, funcs, base, override) {
  51. var visitor = funcs ? exports.make(funcs, base) : base
  52. ;(function c(node, st, override) {
  53. visitor[override || node.type](node, st, c)
  54. })(node, state, override)
  55. }
  56. function makeTest(test) {
  57. if (typeof test == "string")
  58. return function (type) { return type == test; }
  59. else if (!test)
  60. return function () { return true; }
  61. else
  62. return test
  63. }
  64. var Found = function Found(node, state) { this.node = node; this.state = state };
  65. // Find a node with a given start, end, and type (all are optional,
  66. // null can be used as wildcard). Returns a {node, state} object, or
  67. // undefined when it doesn't find a matching node.
  68. function findNodeAt(node, start, end, test, base, state) {
  69. test = makeTest(test)
  70. if (!base) base = exports.base
  71. try {
  72. ;(function c(node, st, override) {
  73. var type = override || node.type
  74. if ((start == null || node.start <= start) &&
  75. (end == null || node.end >= end))
  76. base[type](node, st, c)
  77. if ((start == null || node.start == start) &&
  78. (end == null || node.end == end) &&
  79. test(type, node))
  80. throw new Found(node, st)
  81. })(node, state)
  82. } catch (e) {
  83. if (e instanceof Found) return e
  84. throw e
  85. }
  86. }
  87. // Find the innermost node of a given type that contains the given
  88. // position. Interface similar to findNodeAt.
  89. function findNodeAround(node, pos, test, base, state) {
  90. test = makeTest(test)
  91. if (!base) base = exports.base
  92. try {
  93. ;(function c(node, st, override) {
  94. var type = override || node.type
  95. if (node.start > pos || node.end < pos) return
  96. base[type](node, st, c)
  97. if (test(type, node)) throw new Found(node, st)
  98. })(node, state)
  99. } catch (e) {
  100. if (e instanceof Found) return e
  101. throw e
  102. }
  103. }
  104. // Find the outermost matching node after a given position.
  105. function findNodeAfter(node, pos, test, base, state) {
  106. test = makeTest(test)
  107. if (!base) base = exports.base
  108. try {
  109. ;(function c(node, st, override) {
  110. if (node.end < pos) return
  111. var type = override || node.type
  112. if (node.start >= pos && test(type, node)) throw new Found(node, st)
  113. base[type](node, st, c)
  114. })(node, state)
  115. } catch (e) {
  116. if (e instanceof Found) return e
  117. throw e
  118. }
  119. }
  120. // Find the outermost matching node before a given position.
  121. function findNodeBefore(node, pos, test, base, state) {
  122. test = makeTest(test)
  123. if (!base) base = exports.base
  124. var max
  125. ;(function c(node, st, override) {
  126. if (node.start > pos) return
  127. var type = override || node.type
  128. if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node))
  129. max = new Found(node, st)
  130. base[type](node, st, c)
  131. })(node, state)
  132. return max
  133. }
  134. // Fallback to an Object.create polyfill for older environments.
  135. var create = Object.create || function(proto) {
  136. function Ctor() {}
  137. Ctor.prototype = proto
  138. return new Ctor
  139. }
  140. // Used to create a custom walker. Will fill in all missing node
  141. // type properties with the defaults.
  142. function make(funcs, base) {
  143. if (!base) base = exports.base
  144. var visitor = create(base)
  145. for (var type in funcs) visitor[type] = funcs[type]
  146. return visitor
  147. }
  148. function skipThrough(node, st, c) { c(node, st) }
  149. function ignore(_node, _st, _c) {}
  150. // Node walkers.
  151. var base = {}
  152. base.Program = base.BlockStatement = function (node, st, c) {
  153. for (var i = 0; i < node.body.length; ++i)
  154. c(node.body[i], st, "Statement")
  155. }
  156. base.Statement = skipThrough
  157. base.EmptyStatement = ignore
  158. base.ExpressionStatement = base.ParenthesizedExpression =
  159. function (node, st, c) { return c(node.expression, st, "Expression"); }
  160. base.IfStatement = function (node, st, c) {
  161. c(node.test, st, "Expression")
  162. c(node.consequent, st, "Statement")
  163. if (node.alternate) c(node.alternate, st, "Statement")
  164. }
  165. base.LabeledStatement = function (node, st, c) { return c(node.body, st, "Statement"); }
  166. base.BreakStatement = base.ContinueStatement = ignore
  167. base.WithStatement = function (node, st, c) {
  168. c(node.object, st, "Expression")
  169. c(node.body, st, "Statement")
  170. }
  171. base.SwitchStatement = function (node, st, c) {
  172. c(node.discriminant, st, "Expression")
  173. for (var i = 0; i < node.cases.length; ++i) {
  174. var cs = node.cases[i]
  175. if (cs.test) c(cs.test, st, "Expression")
  176. for (var j = 0; j < cs.consequent.length; ++j)
  177. c(cs.consequent[j], st, "Statement")
  178. }
  179. }
  180. base.ReturnStatement = base.YieldExpression = base.AwaitExpression = function (node, st, c) {
  181. if (node.argument) c(node.argument, st, "Expression")
  182. }
  183. base.ThrowStatement = base.SpreadElement =
  184. function (node, st, c) { return c(node.argument, st, "Expression"); }
  185. base.TryStatement = function (node, st, c) {
  186. c(node.block, st, "Statement")
  187. if (node.handler) c(node.handler, st)
  188. if (node.finalizer) c(node.finalizer, st, "Statement")
  189. }
  190. base.CatchClause = function (node, st, c) {
  191. c(node.param, st, "Pattern")
  192. c(node.body, st, "ScopeBody")
  193. }
  194. base.WhileStatement = base.DoWhileStatement = function (node, st, c) {
  195. c(node.test, st, "Expression")
  196. c(node.body, st, "Statement")
  197. }
  198. base.ForStatement = function (node, st, c) {
  199. if (node.init) c(node.init, st, "ForInit")
  200. if (node.test) c(node.test, st, "Expression")
  201. if (node.update) c(node.update, st, "Expression")
  202. c(node.body, st, "Statement")
  203. }
  204. base.ForInStatement = base.ForOfStatement = function (node, st, c) {
  205. c(node.left, st, "ForInit")
  206. c(node.right, st, "Expression")
  207. c(node.body, st, "Statement")
  208. }
  209. base.ForInit = function (node, st, c) {
  210. if (node.type == "VariableDeclaration") c(node, st)
  211. else c(node, st, "Expression")
  212. }
  213. base.DebuggerStatement = ignore
  214. base.FunctionDeclaration = function (node, st, c) { return c(node, st, "Function"); }
  215. base.VariableDeclaration = function (node, st, c) {
  216. for (var i = 0; i < node.declarations.length; ++i)
  217. c(node.declarations[i], st)
  218. }
  219. base.VariableDeclarator = function (node, st, c) {
  220. c(node.id, st, "Pattern")
  221. if (node.init) c(node.init, st, "Expression")
  222. }
  223. base.Function = function (node, st, c) {
  224. if (node.id) c(node.id, st, "Pattern")
  225. for (var i = 0; i < node.params.length; i++)
  226. c(node.params[i], st, "Pattern")
  227. c(node.body, st, node.expression ? "ScopeExpression" : "ScopeBody")
  228. }
  229. // FIXME drop these node types in next major version
  230. // (They are awkward, and in ES6 every block can be a scope.)
  231. base.ScopeBody = function (node, st, c) { return c(node, st, "Statement"); }
  232. base.ScopeExpression = function (node, st, c) { return c(node, st, "Expression"); }
  233. base.Pattern = function (node, st, c) {
  234. if (node.type == "Identifier")
  235. c(node, st, "VariablePattern")
  236. else if (node.type == "MemberExpression")
  237. c(node, st, "MemberPattern")
  238. else
  239. c(node, st)
  240. }
  241. base.VariablePattern = ignore
  242. base.MemberPattern = skipThrough
  243. base.RestElement = function (node, st, c) { return c(node.argument, st, "Pattern"); }
  244. base.ArrayPattern = function (node, st, c) {
  245. for (var i = 0; i < node.elements.length; ++i) {
  246. var elt = node.elements[i]
  247. if (elt) c(elt, st, "Pattern")
  248. }
  249. }
  250. base.ObjectPattern = function (node, st, c) {
  251. for (var i = 0; i < node.properties.length; ++i)
  252. c(node.properties[i].value, st, "Pattern")
  253. }
  254. base.Expression = skipThrough
  255. base.ThisExpression = base.Super = base.MetaProperty = ignore
  256. base.ArrayExpression = function (node, st, c) {
  257. for (var i = 0; i < node.elements.length; ++i) {
  258. var elt = node.elements[i]
  259. if (elt) c(elt, st, "Expression")
  260. }
  261. }
  262. base.ObjectExpression = function (node, st, c) {
  263. for (var i = 0; i < node.properties.length; ++i)
  264. c(node.properties[i], st)
  265. }
  266. base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration
  267. base.SequenceExpression = base.TemplateLiteral = function (node, st, c) {
  268. for (var i = 0; i < node.expressions.length; ++i)
  269. c(node.expressions[i], st, "Expression")
  270. }
  271. base.UnaryExpression = base.UpdateExpression = function (node, st, c) {
  272. c(node.argument, st, "Expression")
  273. }
  274. base.BinaryExpression = base.LogicalExpression = function (node, st, c) {
  275. c(node.left, st, "Expression")
  276. c(node.right, st, "Expression")
  277. }
  278. base.AssignmentExpression = base.AssignmentPattern = function (node, st, c) {
  279. c(node.left, st, "Pattern")
  280. c(node.right, st, "Expression")
  281. }
  282. base.ConditionalExpression = function (node, st, c) {
  283. c(node.test, st, "Expression")
  284. c(node.consequent, st, "Expression")
  285. c(node.alternate, st, "Expression")
  286. }
  287. base.NewExpression = base.CallExpression = function (node, st, c) {
  288. c(node.callee, st, "Expression")
  289. if (node.arguments) for (var i = 0; i < node.arguments.length; ++i)
  290. c(node.arguments[i], st, "Expression")
  291. }
  292. base.MemberExpression = function (node, st, c) {
  293. c(node.object, st, "Expression")
  294. if (node.computed) c(node.property, st, "Expression")
  295. }
  296. base.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (node, st, c) {
  297. if (node.declaration)
  298. c(node.declaration, st, node.type == "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression")
  299. if (node.source) c(node.source, st, "Expression")
  300. }
  301. base.ExportAllDeclaration = function (node, st, c) {
  302. c(node.source, st, "Expression")
  303. }
  304. base.ImportDeclaration = function (node, st, c) {
  305. for (var i = 0; i < node.specifiers.length; i++)
  306. c(node.specifiers[i], st)
  307. c(node.source, st, "Expression")
  308. }
  309. base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.Literal = ignore
  310. base.TaggedTemplateExpression = function (node, st, c) {
  311. c(node.tag, st, "Expression")
  312. c(node.quasi, st)
  313. }
  314. base.ClassDeclaration = base.ClassExpression = function (node, st, c) { return c(node, st, "Class"); }
  315. base.Class = function (node, st, c) {
  316. if (node.id) c(node.id, st, "Pattern")
  317. if (node.superClass) c(node.superClass, st, "Expression")
  318. for (var i = 0; i < node.body.body.length; i++)
  319. c(node.body.body[i], st)
  320. }
  321. base.MethodDefinition = base.Property = function (node, st, c) {
  322. if (node.computed) c(node.key, st, "Expression")
  323. c(node.value, st, "Expression")
  324. }
  325. exports.simple = simple;
  326. exports.ancestor = ancestor;
  327. exports.recursive = recursive;
  328. exports.findNodeAt = findNodeAt;
  329. exports.findNodeAround = findNodeAround;
  330. exports.findNodeAfter = findNodeAfter;
  331. exports.findNodeBefore = findNodeBefore;
  332. exports.make = make;
  333. exports.base = base;
  334. Object.defineProperty(exports, '__esModule', { value: true });
  335. })));