convert-ast.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.convertAst = void 0;
  4. const ts = require("typescript");
  5. const util_1 = require("./util");
  6. /**
  7. * Takes a `ts.SourceFile` and creates data structures that are easier (or more performant) to traverse.
  8. * Note that there is only a performance gain if you can reuse these structures. It's not recommended for one-time AST walks.
  9. */
  10. function convertAst(sourceFile) {
  11. const wrapped = {
  12. node: sourceFile,
  13. parent: undefined,
  14. kind: ts.SyntaxKind.SourceFile,
  15. children: [],
  16. next: undefined,
  17. skip: undefined,
  18. };
  19. const flat = [];
  20. let current = wrapped;
  21. function collectChildren(node) {
  22. current.children.push({
  23. node,
  24. parent: current,
  25. kind: node.kind,
  26. children: [],
  27. next: undefined,
  28. skip: undefined,
  29. });
  30. }
  31. const stack = [];
  32. while (true) {
  33. if (current.children.length === 0) {
  34. ts.forEachChild(current.node, collectChildren);
  35. if (current.children.length === 0) {
  36. current = current.parent; // nothing to do here, go back to parent
  37. }
  38. else {
  39. // recurse into first child
  40. const firstChild = current.children[0];
  41. current.next = firstChild;
  42. flat.push(firstChild.node);
  43. if (util_1.isNodeKind(firstChild.kind))
  44. current = firstChild;
  45. stack.push(1); // set index in stack so we know where to continue processing children
  46. }
  47. }
  48. else {
  49. const index = stack[stack.length - 1];
  50. if (index < current.children.length) { // handles 2nd child to the last
  51. const currentChild = current.children[index];
  52. flat.push(currentChild.node);
  53. let previous = current.children[index - 1];
  54. while (previous.children.length !== 0) {
  55. previous.skip = currentChild;
  56. previous = previous.children[previous.children.length - 1];
  57. }
  58. previous.skip = previous.next = currentChild;
  59. ++stack[stack.length - 1];
  60. if (util_1.isNodeKind(currentChild.kind))
  61. current = currentChild; // recurse into child
  62. }
  63. else {
  64. // done on this node
  65. if (stack.length === 1)
  66. break;
  67. // remove index from stack and go back to parent
  68. stack.pop();
  69. current = current.parent;
  70. }
  71. }
  72. }
  73. return {
  74. wrapped,
  75. flat,
  76. };
  77. }
  78. exports.convertAst = convertAst;
  79. //# sourceMappingURL=convert-ast.js.map