add outline funton for tcl
/ build_and_publish (push) Successful in 33s

This commit is contained in:
Christoph Brandau
2025-07-01 15:39:49 +02:00
parent d3dd57aa91
commit d76cd7559a
2 changed files with 143 additions and 1 deletions
+135
View File
@@ -136,3 +136,138 @@ export function hoverCdlHandler(document: vscode.TextDocument, position: vscode.
} }
return undefined return undefined
} }
export function tclDocumentSymbolProvider(document: vscode.TextDocument): vscode.DocumentSymbol[] {
const symbols: vscode.DocumentSymbol[] = []
const lines = document.getText().split("\n")
interface Scope {
name: string
symbol: vscode.DocumentSymbol
startLine: number
braceCount: number
children: Scope[]
}
const rootScope: Scope = {
name: "",
symbol: new vscode.DocumentSymbol(
"root",
"",
vscode.SymbolKind.Namespace,
new vscode.Range(0, 0, lines.length, 0),
new vscode.Range(0, 0, 0, 0)
),
startLine: 0,
braceCount: 0,
children: []
}
let scopeStack: Scope[] = [rootScope]
const namespaceRegex = /^\s*namespace\s+eval\s+([^\s\{]+)/
const procRegex = /^\s*proc\s+([^\s\{]+)\s+\{.*\}\s+\{/
const eventStartRegex = /^\s*LIB_GE_command_buffer_edit_(prepend|append|insert)\b/
let pendingEvent: { editType: string; startLine: number } | null = null
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
const nsMatch = line.match(namespaceRegex)
const procMatch = line.match(procRegex)
const eventStartMatch = line.match(eventStartRegex)
if (pendingEvent) {
// Wir suchen nach schließender Klammer mit Eventnamen danach
const closeMatch = line.match(/^\s*\}\s*(\w+)\s*$/)
if (closeMatch) {
const eventName = closeMatch[1]
const eventSymbol = new vscode.DocumentSymbol(
eventName,
`Event (${pendingEvent.editType})`,
vscode.SymbolKind.Event,
new vscode.Range(pendingEvent.startLine, 0, i, line.length),
new vscode.Range(i, 0, i, line.length)
)
scopeStack[scopeStack.length - 1].children.push({
name: eventName,
symbol: eventSymbol,
startLine: pendingEvent.startLine,
braceCount: 0,
children: []
})
pendingEvent = null
continue // nichts anderes prüfen, wenn wir Event abgeschlossen haben
}
}
if (eventStartMatch) {
// Beginn eines Event-Blocks erkannt
pendingEvent = { editType: eventStartMatch[1], startLine: i }
continue
}
if (nsMatch) {
const nsName = nsMatch[1]
const nsSymbol = new vscode.DocumentSymbol(
nsName,
"Namespace",
vscode.SymbolKind.Namespace,
new vscode.Range(i, 0, i, line.length),
new vscode.Range(i, 0, i, line.length)
)
const nsScope: Scope = {
name: nsName,
symbol: nsSymbol,
startLine: i,
braceCount: 0,
children: []
}
scopeStack[scopeStack.length - 1].children.push(nsScope)
scopeStack.push(nsScope)
} else if (procMatch) {
const procName = procMatch[1]
const procSymbol = new vscode.DocumentSymbol(
procName,
"Procedure",
vscode.SymbolKind.Function,
new vscode.Range(i, 0, i, line.length),
new vscode.Range(i, 0, i, line.length)
)
scopeStack[scopeStack.length - 1].children.push({
name: procName,
symbol: procSymbol,
startLine: i,
braceCount: 0,
children: []
})
}
// Brace-Balancing für Namespaces und Procs
const openCount = (line.match(/\{/g) || []).length
const closeCount = (line.match(/\}/g) || []).length
scopeStack[scopeStack.length - 1].braceCount += openCount - closeCount
while (scopeStack.length > 1 && scopeStack[scopeStack.length - 1].braceCount <= 0) {
const finishedScope = scopeStack.pop()
if (finishedScope) {
finishedScope.symbol.range = new vscode.Range(
finishedScope.startLine,
0,
i,
line.length
)
}
}
}
function collectSymbols(scope: Scope): vscode.DocumentSymbol[] {
for (const child of scope.children) {
child.symbol.children = collectSymbols(child)
}
return scope.children.map((child) => child.symbol)
}
return collectSymbols(rootScope)
}
+8 -1
View File
@@ -11,7 +11,8 @@ import {
hoverCdlHandler, hoverCdlHandler,
formatDefFile, formatDefFile,
isFirstLineMachine, isFirstLineMachine,
diagnosticHandler diagnosticHandler,
tclDocumentSymbolProvider
} from "./common/handlers" } from "./common/handlers"
let client: LanguageClient let client: LanguageClient
@@ -81,6 +82,12 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(formatDefProvider) context.subscriptions.push(formatDefProvider)
const tclOutlineProvider = vscode.languages.registerDocumentSymbolProvider(
{ scheme: "file", language: "tcl" },
{ provideDocumentSymbols: tclDocumentSymbolProvider }
)
context.subscriptions.push(tclOutlineProvider)
// Diagnostics collection // Diagnostics collection
const diagnosticCollectionCdl = vscode.languages.createDiagnosticCollection("cdl") const diagnosticCollectionCdl = vscode.languages.createDiagnosticCollection("cdl")
const diagnosticCollectionDef = vscode.languages.createDiagnosticCollection("def") const diagnosticCollectionDef = vscode.languages.createDiagnosticCollection("def")