You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
2.8 KiB
JavaScript
88 lines
2.8 KiB
JavaScript
'use strict';
|
|
|
|
const archy = require("archy");
|
|
const chalk = require("chalk");
|
|
const memoizee = require("memoizee");
|
|
const assureArray = require("assure-array");
|
|
const util = require("util");
|
|
|
|
const colorizedNodeType = require("./render/colorize-type");
|
|
const shortDescription = require("./render/short-description");
|
|
const sectionTag = require("./render/section-tag");
|
|
|
|
module.exports = function visualizeAST(ast) {
|
|
let indexedItems = []; // NOTE: Impure, but is necessary to make getItemAtIndex work...
|
|
|
|
function sectionLabel(name, items) {
|
|
return {
|
|
label: chalk.yellow(`${name}:`),
|
|
nodes: items
|
|
}
|
|
}
|
|
|
|
function convertChildNodes(key, childNodes) {
|
|
let arrayifiedNodes = assureArray(childNodes);
|
|
|
|
let treeNodes = arrayifiedNodes.map((node) => {
|
|
let treeNode = astNodeToTreeNode(node);
|
|
treeNode.label = sectionTag(key, {isArray: Array.isArray(childNodes)}) + " " + treeNode.label;
|
|
return treeNode;
|
|
});
|
|
|
|
return treeNodes;
|
|
}
|
|
|
|
function astNodeToTreeNode(astNode) {
|
|
indexedItems.push(astNode);
|
|
|
|
let nodeLabel = `${chalk.bold(colorizedNodeType(astNode))} ${shortDescription(astNode)}`;
|
|
|
|
let primitiveProperties = [], singleChildren = [], multipleChildren = [];
|
|
|
|
Object.keys(astNode).forEach((key) => {
|
|
if (key === "loc" || key === "range") {
|
|
/* These are Esprima annotations. */
|
|
return;
|
|
}
|
|
|
|
let value = astNode[key];
|
|
|
|
if (typeof value === "string" || typeof value === "boolean" || typeof value === "number" || value == null) {
|
|
primitiveProperties.push(key);
|
|
} else if (Array.isArray(value)) {
|
|
if (value.length > 0) {
|
|
multipleChildren.push(key);
|
|
}
|
|
} else if (typeof value === "object" && value.type != null) {
|
|
singleChildren.push(key);
|
|
} else {
|
|
throw new Error(`Encountered unrecognized value type in AST: ${typeof value} -- ${util.inspect(value)}`);
|
|
}
|
|
});
|
|
|
|
let childNodes = (singleChildren.concat(multipleChildren)).map((key) => {
|
|
return convertChildNodes(key, astNode[key]);
|
|
}).reduce((combined, array) => {
|
|
return combined.concat(array);
|
|
}, []);
|
|
|
|
return {
|
|
label: nodeLabel,
|
|
nodes: childNodes
|
|
}
|
|
}
|
|
|
|
return {
|
|
getString: memoizee(function getString() {
|
|
let treeNodes = astNodeToTreeNode(ast);
|
|
return archy(treeNodes);
|
|
}),
|
|
getLines: function getLines() {
|
|
return this.getString().split("\n");
|
|
},
|
|
getItemAtIndex: function getItemAtIndex(index) {
|
|
return indexedItems[index];
|
|
}
|
|
}
|
|
}
|