118 lines
3.4 KiB
TypeScript
118 lines
3.4 KiB
TypeScript
#!/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<string, any>) => {
|
|
const metadata: Record<string, { params: string[] }> = {}
|
|
|
|
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<string, any> = {}
|
|
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<string, { params: string[] }> = {}
|
|
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`
|
|
)
|