./bin/parser-tree.ts
This commit is contained in:
parent
e1859c1bda
commit
88ee108a1e
192
bin/parser-tree.ts
Executable file
192
bin/parser-tree.ts
Executable file
|
|
@ -0,0 +1,192 @@
|
|||
#!/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<string>
|
||||
isRecursive?: boolean
|
||||
}
|
||||
|
||||
// Parse the parser file and extract method calls
|
||||
function analyzeParser(filePath: string): Map<string, CallInfo> {
|
||||
const content = readFileSync(filePath, 'utf-8')
|
||||
const lines = content.split('\n')
|
||||
const methods = new Map<string, CallInfo>()
|
||||
|
||||
// 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<string, CallInfo>,
|
||||
visited: Set<string>,
|
||||
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<string>()
|
||||
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<string, number>()
|
||||
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`)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user