"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 |