#!/usr/bin/env bun // WARNING: [[ No human has been anywhere near this file. It's pure Claude slop. // Enter at your own risk. ]] import { readFileSync } from 'fs' type CallInfo = { method: string line: number calls: Set isRecursive?: boolean } // Parse the parser file and extract method calls function analyzeParser(filePath: string): Map { const content = readFileSync(filePath, 'utf-8') const lines = content.split('\n') const methods = new Map() // Find all method definitions const methodRegex = /^\s*(\w+)\s*\([^)]*\):\s*/ let currentMethod: string | null = null let braceDepth = 0 let classDepth = 0 for (let i = 0; i < lines.length; i++) { const line = lines[i] || '' // Track if we're inside the Parser class if (line.includes('class Parser')) { classDepth = braceDepth + 1 // Will be the depth after we process this line's brace } // Check for method definition (only inside class, at class level) // Check BEFORE incrementing braceDepth if (classDepth > 0 && braceDepth === classDepth) { const methodMatch = line.match(methodRegex) if (methodMatch && !line.includes('class ')) { currentMethod = methodMatch[1]! methods.set(currentMethod, { method: currentMethod, line: i + 1, calls: new Set() }) } } // Track brace depth braceDepth += (line.match(/{/g) || []).length braceDepth -= (line.match(/}/g) || []).length // Find method calls within current method if (currentMethod && braceDepth > 0) { // Match this.methodName() calls const callRegex = /this\.(\w+)\s*\(/g let match while ((match = callRegex.exec(line)) !== null) { const calledMethod = match[1]! const info = methods.get(currentMethod)! info.calls.add(calledMethod) // Mark recursive calls if (calledMethod === currentMethod) { info.isRecursive = true } } } // Reset when method ends if (braceDepth === 0) { currentMethod = null } } return methods } // Build tree structure starting from a root method function buildTree( method: string, callGraph: Map, visited: Set, indent = '', isLast = true, depth = 0, maxDepth = 3 ): string[] { const lines: string[] = [] const info = callGraph.get(method) if (!info) return lines // Add current method const prefix = depth === 0 ? '' : (isLast ? '└─> ' : '├─> ') const suffix = info.isRecursive ? ' (recursive)' : '' const lineNum = `[line ${info.line}]` lines.push(`${indent}${prefix}${method}() ${lineNum}${suffix}`) // Stop if we've reached max depth if (depth >= maxDepth) { return lines } // Prevent infinite recursion in tree display if (visited.has(method)) { return lines } const newVisited = new Set(visited) newVisited.add(method) // Helper methods to filter out (low-level utilities) const helperPatterns = /^(is|next|peek|expect|current|op)/i // Get sorted unique calls (filter out recursive self-calls for display) const calls = Array.from(info.calls) .filter(c => callGraph.has(c)) // Only show parser methods .filter(c => c !== method) // Don't show immediate self-recursion .filter(c => !helperPatterns.test(c)) // Filter out helpers .sort() // Add children const newIndent = indent + (isLast ? ' ' : '│ ') calls.forEach((call, idx) => { const childLines = buildTree( call, callGraph, newVisited, newIndent, idx === calls.length - 1, depth + 1, maxDepth ) lines.push(...childLines) }) return lines } // Main const parserPath = './src/parser/parser2.ts' const maxDepth = parseInt(process.argv[2] || '5') console.log('Parser Call Tree for', parserPath) console.log(`Max depth: ${maxDepth}`) console.log('═'.repeat(60)) console.log() const callGraph = analyzeParser(parserPath) // Start from parse() method const tree = buildTree('parse', callGraph, new Set(), '', true, 0, maxDepth) console.log(tree.join('\n')) // Show some stats console.log('\n' + '═'.repeat(60)) console.log('Stats:') console.log(` Total methods: ${callGraph.size}`) console.log(` Entry point: parse()`) // Find methods that are never called (potential dead code or entry points) const allCalled = new Set() for (const info of callGraph.values()) { info.calls.forEach(c => allCalled.add(c)) } const uncalled = Array.from(callGraph.keys()) .filter(m => !allCalled.has(m) && m !== 'parse') .sort() if (uncalled.length > 0) { console.log(`\n Uncalled methods: ${uncalled.join(', ')}`) } // Find most-called methods const callCount = new Map() for (const info of callGraph.values()) { for (const called of info.calls) { callCount.set(called, (callCount.get(called) || 0) + 1) } } const topCalled = Array.from(callCount.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, 5) console.log(`\n Most-called methods:`) for (const [method, count] of topCalled) { console.log(` ${method}() - called ${count} times`) }