79 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			79 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
"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
 |