traverse.js 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import { createPath } from "./node-path";
  2. import { unionTypesMap, nodeAndUnionTypes } from "./nodes"; // recursively walks the AST starting at the given node. The callback is invoked for
  3. // and object that has a 'type' property.
  4. function walk(context, callback) {
  5. var stop = false;
  6. function innerWalk(context, callback) {
  7. if (stop) {
  8. return;
  9. }
  10. var node = context.node;
  11. if (node._deleted === true) {
  12. return;
  13. }
  14. var path = createPath(context);
  15. callback(node.type, path);
  16. if (path.shouldStop) {
  17. stop = true;
  18. return;
  19. }
  20. Object.keys(node).forEach(function (prop) {
  21. var value = node[prop];
  22. if (value === null || value === undefined) {
  23. return;
  24. }
  25. var valueAsArray = Array.isArray(value) ? value : [value];
  26. valueAsArray.forEach(function (childNode) {
  27. if (typeof childNode.type === "string") {
  28. var childContext = {
  29. node: childNode,
  30. parentKey: prop,
  31. parentPath: path,
  32. shouldStop: false,
  33. inList: Array.isArray(value)
  34. };
  35. innerWalk(childContext, callback);
  36. }
  37. });
  38. });
  39. }
  40. innerWalk(context, callback);
  41. }
  42. var noop = function noop() {};
  43. export function traverse(node, visitors) {
  44. var before = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : noop;
  45. var after = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : noop;
  46. Object.keys(visitors).forEach(function (visitor) {
  47. if (!nodeAndUnionTypes.includes(visitor)) {
  48. throw new Error("Unexpected visitor ".concat(visitor));
  49. }
  50. });
  51. var context = {
  52. node: node,
  53. inList: false,
  54. shouldStop: false,
  55. parentPath: null,
  56. parentKey: null
  57. };
  58. walk(context, function (type, path) {
  59. if (typeof visitors[type] === "function") {
  60. before(type, path);
  61. visitors[type](path);
  62. after(type, path);
  63. }
  64. var unionTypes = unionTypesMap[type];
  65. if (!unionTypes) {
  66. throw new Error("Unexpected node type ".concat(type));
  67. }
  68. unionTypes.forEach(function (unionType) {
  69. if (typeof visitors[unionType] === "function") {
  70. before(unionType, path);
  71. visitors[unionType](path);
  72. after(unionType, path);
  73. }
  74. });
  75. });
  76. }