This commit is contained in:
@@ -136,3 +136,138 @@ export function hoverCdlHandler(document: vscode.TextDocument, position: vscode.
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ import {
|
||||
hoverCdlHandler,
|
||||
formatDefFile,
|
||||
isFirstLineMachine,
|
||||
diagnosticHandler
|
||||
diagnosticHandler,
|
||||
tclDocumentSymbolProvider
|
||||
} from "./common/handlers"
|
||||
|
||||
let client: LanguageClient
|
||||
@@ -81,6 +82,12 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
context.subscriptions.push(formatDefProvider)
|
||||
|
||||
const tclOutlineProvider = vscode.languages.registerDocumentSymbolProvider(
|
||||
{ scheme: "file", language: "tcl" },
|
||||
{ provideDocumentSymbols: tclDocumentSymbolProvider }
|
||||
)
|
||||
context.subscriptions.push(tclOutlineProvider)
|
||||
|
||||
// Diagnostics collection
|
||||
const diagnosticCollectionCdl = vscode.languages.createDiagnosticCollection("cdl")
|
||||
const diagnosticCollectionDef = vscode.languages.createDiagnosticCollection("def")
|
||||
|
||||
Reference in New Issue
Block a user