| "use strict"; |
| Object.defineProperty(exports, "__esModule", { value: true }); |
| exports.convertAst = void 0; |
| const ts = require("typescript"); |
| const util_1 = require("./util"); |
| /** |
| * Takes a `ts.SourceFile` and creates data structures that are easier (or more performant) to traverse. |
| * Note that there is only a performance gain if you can reuse these structures. It's not recommended for one-time AST walks. |
| */ |
| function convertAst(sourceFile) { |
| const wrapped = { |
| node: sourceFile, |
| parent: undefined, |
| kind: ts.SyntaxKind.SourceFile, |
| children: [], |
| next: undefined, |
| skip: undefined, |
| }; |
| const flat = []; |
| let current = wrapped; |
| function collectChildren(node) { |
| current.children.push({ |
| node, |
| parent: current, |
| kind: node.kind, |
| children: [], |
| next: undefined, |
| skip: undefined, |
| }); |
| } |
| const stack = []; |
| while (true) { |
| if (current.children.length === 0) { |
| ts.forEachChild(current.node, collectChildren); |
| if (current.children.length === 0) { |
| current = current.parent; // nothing to do here, go back to parent |
| } |
| else { |
| // recurse into first child |
| const firstChild = current.children[0]; |
| current.next = firstChild; |
| flat.push(firstChild.node); |
| if (util_1.isNodeKind(firstChild.kind)) |
| current = firstChild; |
| stack.push(1); // set index in stack so we know where to continue processing children |
| } |
| } |
| else { |
| const index = stack[stack.length - 1]; |
| if (index < current.children.length) { // handles 2nd child to the last |
| const currentChild = current.children[index]; |
| flat.push(currentChild.node); |
| let previous = current.children[index - 1]; |
| while (previous.children.length !== 0) { |
| previous.skip = currentChild; |
| previous = previous.children[previous.children.length - 1]; |
| } |
| previous.skip = previous.next = currentChild; |
| ++stack[stack.length - 1]; |
| if (util_1.isNodeKind(currentChild.kind)) |
| current = currentChild; // recurse into child |
| } |
| else { |
| // done on this node |
| if (stack.length === 1) |
| break; |
| // remove index from stack and go back to parent |
| stack.pop(); |
| current = current.parent; |
| } |
| } |
| } |
| return { |
| wrapped, |
| flat, |
| }; |
| } |
| exports.convertAst = convertAst; |
| //# sourceMappingURL=convert-ast.js.map |