You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
2.8 KiB
79 lines
2.8 KiB
"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
|