feat(cdl): add CDL event handler parsing and snippet support
build_and_puplish.yml / build_and_publish (release) Successful in 36s
build_and_puplish.yml / build_and_publish (release) Successful in 36s
This adds a small DSL-aware helper to extract CDL event declarations and generate a ready-to-use snippet. It also extends hover support to show the snippet and parameter hints for CDL events, improving developer productivity. - Generate a MOM event handler scaffold and local vars - Hover shows the generated snippet and mom_ parameter hints
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
export interface CdlEventHandler {
|
||||
eventName: string
|
||||
parameterNames: string[]
|
||||
}
|
||||
|
||||
function structuralCode(line: string): string {
|
||||
let result = ""
|
||||
let inString = false
|
||||
let escaped = false
|
||||
|
||||
for (const character of line) {
|
||||
if (escaped) {
|
||||
escaped = false
|
||||
result += inString ? " " : character
|
||||
continue
|
||||
}
|
||||
if (character === "\\") {
|
||||
escaped = true
|
||||
result += inString ? " " : character
|
||||
continue
|
||||
}
|
||||
if (character === '"') {
|
||||
inString = !inString
|
||||
result += " "
|
||||
continue
|
||||
}
|
||||
if (character === "#" && !inString) {
|
||||
break
|
||||
}
|
||||
result += inString ? " " : character
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function braceDelta(line: string): number {
|
||||
let delta = 0
|
||||
for (const character of structuralCode(line)) {
|
||||
if (character === "{") {
|
||||
delta += 1
|
||||
} else if (character === "}") {
|
||||
delta -= 1
|
||||
}
|
||||
}
|
||||
return delta
|
||||
}
|
||||
|
||||
export function cdlEventHandlerAtLine(
|
||||
source: string,
|
||||
declarationLine: number
|
||||
): CdlEventHandler | undefined {
|
||||
const lines = source.split(/\r?\n/)
|
||||
const declaration = lines[declarationLine]
|
||||
if (declaration === undefined) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const eventMatch = /^\s*EVENT\s+([^\s{]+)/.exec(structuralCode(declaration))
|
||||
if (!eventMatch) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const parameterNames: string[] = []
|
||||
let eventOpened = false
|
||||
let depth = 0
|
||||
|
||||
for (let lineNumber = declarationLine; lineNumber < lines.length; lineNumber++) {
|
||||
const line = lines[lineNumber]
|
||||
const code = structuralCode(line)
|
||||
|
||||
if (eventOpened && depth === 1) {
|
||||
const parameterMatch = /^\s*PARAM\s+([^\s{]+)/.exec(code)
|
||||
if (parameterMatch) {
|
||||
parameterNames.push(parameterMatch[1])
|
||||
}
|
||||
}
|
||||
|
||||
const delta = braceDelta(line)
|
||||
if (!eventOpened && delta > 0) {
|
||||
eventOpened = true
|
||||
}
|
||||
if (eventOpened) {
|
||||
depth += delta
|
||||
if (depth <= 0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
eventName: eventMatch[1],
|
||||
parameterNames
|
||||
}
|
||||
}
|
||||
|
||||
function momEventName(eventName: string): string {
|
||||
return `MOM_${eventName.replace(/^MOM_/i, "")}`
|
||||
}
|
||||
|
||||
function momVariableName(parameterName: string): string {
|
||||
return `mom_${parameterName.replace(/^mom_/i, "")}`
|
||||
}
|
||||
|
||||
export function createCdlEventHandlerSnippet(handler: CdlEventHandler): string {
|
||||
const globals = [
|
||||
...new Set(handler.parameterNames.map((parameter) => momVariableName(parameter)))
|
||||
]
|
||||
const lines = [`proc ${momEventName(handler.eventName)} { } {`]
|
||||
|
||||
if (globals.length > 0) {
|
||||
lines.push(...globals.map((variable) => ` global ${variable}`), "")
|
||||
}
|
||||
lines.push(" #Put your UDE Handler Tcl here", "", "}")
|
||||
|
||||
return lines.join("\n")
|
||||
}
|
||||
Reference in New Issue
Block a user