#!/usr/bin/env bun /** * Generates prelude metadata for the VSCode extension. * - Prelude names (for parser scope tracking) * - Function signatures (for autocomplete) */ import { writeFileSync } from 'fs' import { join } from 'path' import { globals } from '../../src/prelude' // Extract parameter names from a function const extractParams = (fn: Function): string[] => { const fnStr = fn.toString() const match = fnStr.match(/\(([^)]*)\)/) if (!match) return [] const paramsStr = match[1]!.trim() if (!paramsStr) return [] // Split by comma, but be careful of default values with commas const params: string[] = [] let current = '' let inString = false let stringChar = '' for (let i = 0; i < paramsStr.length; i++) { const char = paramsStr[i] if ((char === '"' || char === "'") && (i === 0 || paramsStr[i - 1] !== '\\')) { if (!inString) { inString = true stringChar = char } else if (char === stringChar) { inString = false } } if (char === ',' && !inString) { params.push(current.trim()) current = '' } else { current += char } } if (current.trim()) params.push(current.trim()) return params .map((p) => p.split(/[=:]/)[0]!.trim()) // Handle defaults and types .filter((p) => p && p !== 'this') } // Generate metadata for a module const generateModuleMetadata = (module: Record) => { const metadata: Record = {} for (const [name, value] of Object.entries(module)) { if (typeof value === 'function') { metadata[name] = { params: extractParams(value) } } } return metadata } // Generate names list const names = Object.keys(globals).sort() // Generate module metadata const moduleMetadata: Record = {} for (const [name, value] of Object.entries(globals)) { if (typeof value === 'object' && value !== null && name !== '$') { moduleMetadata[name] = generateModuleMetadata(value) } } // Generate dollar metadata const dollarMetadata: Record = {} if (globals.$ && typeof globals.$ === 'object') { for (const key of Object.keys(globals.$)) { dollarMetadata[key] = { params: [] } } } // Write prelude-names.ts const namesOutput = `// Auto-generated by scripts/generate-prelude-metadata.ts // Do not edit manually - run 'bun run generate-prelude-metadata' to regenerate export const PRELUDE_NAMES = ${JSON.stringify(names, null, 2)} as const ` const namesPath = join(import.meta.dir, '../server/src/metadata/prelude-names.ts') writeFileSync(namesPath, namesOutput) // Write prelude-completions.ts const completionsOutput = `// Auto-generated by scripts/generate-prelude-metadata.ts // Do not edit manually - run 'bun run generate-prelude-metadata' to regenerate export type CompletionMetadata = { params: string[] description?: string } export const completions = { modules: ${JSON.stringify(moduleMetadata, null, 2)}, dollar: ${JSON.stringify(dollarMetadata, null, 2)}, } as const ` const completionsPath = join(import.meta.dir, '../server/src/metadata/prelude-completions.ts') writeFileSync(completionsPath, completionsOutput) console.log(`✓ Generated ${names.length} prelude names to server/src/metadata/prelude-names.ts`) console.log( `✓ Generated completions for ${ Object.keys(moduleMetadata).length } modules to server/src/metadata/prelude-completions.ts`, )