1 line
		
	
	
		
			28 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			1 line
		
	
	
		
			28 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|  | {"version":3,"file":"walk.mjs","sources":["../src/index.js"],"sourcesContent":["// AST walker module for Mozilla Parser API compatible trees\n\n// A simple walk is one where you simply specify callbacks to be\n// called on specific nodes. The last two arguments are optional. A\n// simple use would be\n//\n//     walk.simple(myTree, {\n//         Expression: function(node) { ... }\n//     });\n//\n// to do something with all expressions. All Parser API node types\n// can be used to identify node types, as well as Expression and\n// Statement, which denote categories of nodes.\n//\n// The base argument can be used to pass a custom (recursive)\n// walker, and state can be used to give this walked an initial\n// state.\n\nexport function simple(node, visitors, baseVisitor, state, override) {\n  if (!baseVisitor) baseVisitor = base\n  ;(function c(node, st, override) {\n    let type = override || node.type, found = visitors[type]\n    baseVisitor[type](node, st, c)\n    if (found) found(node, st)\n  })(node, state, override)\n}\n\n// An ancestor walk keeps an array of ancestor nodes (including the\n// current node) and passes them to the callback as third parameter\n// (and also as state parameter when no other state is present).\nexport function ancestor(node, visitors, baseVisitor, state) {\n  let ancestors = []\n  if (!baseVisitor) baseVisitor = base\n  ;(function c(node, st, override) {\n    let type = override || node.type, found = visitors[type]\n    let isNew = node !== ancestors[ancestors.length - 1]\n    if (isNew) ancestors.push(node)\n    baseVisitor[type](node, st, c)\n    if (found) found(node, st || ancestors, ancestors)\n    if (isNew) ancestors.pop()\n  })(node, state)\n}\n\n// A recursive walk is one where your functions override the default\n// walkers. They can modify and replace the state parameter that's\n// threaded through the walk, and can opt how and whether to walk\n// their child nodes (by calling their third argument on these\n// nodes).\nexport function recursive(node, state, funcs, baseVisitor, override) {\n  let visitor = funcs ? make(funcs, baseVisitor || undefined) : baseVisitor\n  ;(function c(node, st, override) {\n    visitor[override || node.type](node, st, c)\n  })(node, state, override)\n}\n\nfunction makeTest(test) {\n  if (typeof test === \"string\")\n    return type => type === test\n  else if (!test)\n    return () => true\n  else\n    return test\n}\n\nclass Found {\n  constructor(node, state) { this.node = node; this.state = state }\n}\n\n// A full walk triggers the callback on each node\nexport function full(node, callback, baseVisitor, state, override) {\n  if (!baseVisitor) baseVisitor = base\n  ;(function c(node, st, override) {\n    let type = override || node.type\n    baseVisitor[type](node, st, c)\n    if (!override) callback(node, st, type)\n  })(node, state, override)\n}\n\n// An fullAncestor walk is like an ancestor walk, but triggers\n// the callback on each node\nexport function fullAncestor(node, callback, baseVisitor, state) {\n  if (!baseVisitor) baseVisitor = base\n  let ancestors = []\n  ;(function c(node, st, override) {\n    let type = override || node.type\n    let isNew = node !== ancestors[ancestors.length - 1]\n    if (isNew) ancestors.push(node)\n    baseVisitor[type](node, st, c)\n    if (!override) callback(node, st || ancestors, ancestors, type)\n    if (isNew) ancestors.pop()\n  })(node, state)\n}\n\n// Find a node with a given start, end, and type (all are optional,\n// null can be used as wildcard). Returns a {node, state} object, or\n// undefined when it doesn't find a matching node.\nexport function findNodeAt(node, start, end, test, baseVisitor, state) {\n  if (!baseVisitor) baseVisitor = base\n  test = makeTest(test)\n  try {\n    (function c(node, st, override) {\n      let type = override || node.type\n      if ((start == null || node.start <= start) &&\n          (end == null || node.end >= end))\n        baseVisitor[type](node, st, c)\n      if ((start == null || node.start === start) &&\n          (end == null || node.end === end) &&\n       |