UNPKG

@ordojs/dev-tools

Version:

Advanced developer tools for OrdoJS with component inspector, AST explorer, and performance profiling

276 lines (274 loc) 6.7 kB
import { EventEmitter } from 'events'; // src/ast-explorer/index.ts var ASTExplorer = class extends EventEmitter { astNodes; isRunning; port; /** * Create a new ASTExplorer instance * * @param port - WebSocket port for AST explorer */ constructor(port = 24681) { super(); this.astNodes = /* @__PURE__ */ new Map(); this.isRunning = false; this.port = port; } /** * Start the AST explorer */ async start() { if (this.isRunning) { console.warn("AST explorer is already running"); return; } try { await this.startWebSocketServer(); this.isRunning = true; console.log(`AST explorer started on port ${this.port}`); this.emit("started"); } catch (error) { console.error("Failed to start AST explorer:", error); this.emit("error", error); throw error; } } /** * Stop the AST explorer */ async stop() { if (!this.isRunning) { console.warn("AST explorer is not running"); return; } try { await this.stopWebSocketServer(); this.isRunning = false; console.log("AST explorer stopped"); this.emit("stopped"); } catch (error) { console.error("Failed to stop AST explorer:", error); this.emit("error", error); throw error; } } /** * Parse source code and create AST * * @param sourceCode - Source code to parse * @param fileName - File name for the AST * @returns AST root node */ parseSourceCode(sourceCode, fileName) { try { const astNode = { type: "Program", position: { start: { line: 1, column: 1 }, end: { line: 1, column: sourceCode.length } }, children: [], value: sourceCode }; this.astNodes.set(fileName, astNode); this.emit("astParsed", { fileName, astNode }); return astNode; } catch (error) { console.error("Failed to parse source code:", error); this.emit("error", error); throw error; } } /** * Get AST for a file * * @param fileName - File name * @returns AST node or undefined */ getAST(fileName) { return this.astNodes.get(fileName); } /** * Get all ASTs * * @returns Map of all ASTs */ getAllASTs() { return new Map(this.astNodes); } /** * Find nodes by type * * @param fileName - File name * @param nodeType - Node type to search for * @returns Array of matching nodes */ findNodesByType(fileName, nodeType) { const ast = this.astNodes.get(fileName); if (!ast) { return []; } return this.findNodesRecursive(ast, nodeType); } /** * Find nodes by value * * @param fileName - File name * @param value - Value to search for * @returns Array of matching nodes */ findNodesByValue(fileName, value) { const ast = this.astNodes.get(fileName); if (!ast) { return []; } return this.findNodesByValueRecursive(ast, value); } /** * Get node path from root * * @param fileName - File name * @param targetNode - Target node * @returns Array of nodes from root to target */ getNodePath(fileName, targetNode) { const ast = this.astNodes.get(fileName); if (!ast) { return []; } return this.findNodePath(ast, targetNode); } /** * Get AST statistics * * @param fileName - File name * @returns AST statistics */ getASTStats(fileName) { const ast = this.astNodes.get(fileName); if (!ast) { return { totalNodes: 0, nodeTypes: {}, maxDepth: 0, averageDepth: 0 }; } const stats = this.calculateASTStats(ast); return stats; } /** * Clear all ASTs */ clearASTs() { this.astNodes.clear(); this.emit("astsCleared"); } /** * Recursively find nodes by type * * @param node - Current node * @param nodeType - Node type to search for * @returns Array of matching nodes */ findNodesRecursive(node, nodeType) { const results = []; if (node.type === nodeType) { results.push(node); } if (node.children) { for (const child of node.children) { results.push(...this.findNodesRecursive(child, nodeType)); } } return results; } /** * Recursively find nodes by value * * @param node - Current node * @param value - Value to search for * @returns Array of matching nodes */ findNodesByValueRecursive(node, value) { const results = []; if (node.value && node.value.includes(value)) { results.push(node); } if (node.children) { for (const child of node.children) { results.push(...this.findNodesByValueRecursive(child, value)); } } return results; } /** * Find path from root to target node * * @param node - Current node * @param targetNode - Target node * @param path - Current path * @returns Path to target node or empty array */ findNodePath(node, targetNode, path = []) { const currentPath = [...path, node]; if (node === targetNode) { return currentPath; } if (node.children) { for (const child of node.children) { const result = this.findNodePath(child, targetNode, currentPath); if (result.length > 0) { return result; } } } return []; } /** * Calculate AST statistics * * @param node - Root node * @param depth - Current depth * @returns AST statistics */ calculateASTStats(node, depth = 0) { let totalNodes = 1; const nodeTypes = { [node.type]: 1 }; let maxDepth = depth; let totalDepth = depth; if (node.children) { for (const child of node.children) { const childStats = this.calculateASTStats(child, depth + 1); totalNodes += childStats.totalNodes; maxDepth = Math.max(maxDepth, childStats.maxDepth); totalDepth += childStats.totalNodes * (depth + 1); for (const [type, count] of Object.entries(childStats.nodeTypes)) { nodeTypes[type] = (nodeTypes[type] || 0) + count; } } } return { totalNodes, nodeTypes, maxDepth, averageDepth: totalDepth / totalNodes }; } /** * Start WebSocket server for AST explorer communication */ async startWebSocketServer() { console.log("Starting WebSocket server for AST explorer..."); } /** * Stop WebSocket server */ async stopWebSocketServer() { console.log("Stopping WebSocket server for AST explorer..."); } }; export { ASTExplorer }; //# sourceMappingURL=index.mjs.map //# sourceMappingURL=index.mjs.map