feat(navigation): add symbol index and LSP navigation features

The changes introduce a Tcl symbol index powering LSP navigation
features across the workspace. A navigation API exposes
snapshots and update hooks, enabling goto-definition,
references, and rename using the index. Background indexing
now watches Tcl files and rebuilds the index to stay in sync.

- Add Tcl symbol index and navigation snapshot API
- Wire go-to-definition, references, and rename using the index
- Watch Tcl files and refresh the index in the background
This commit is contained in:
Christoph Brandau
2026-08-17 09:24:45 +02:00
parent f5bd79f067
commit 35a4357551
8 changed files with 1128 additions and 88 deletions
+15 -4
View File
@@ -2,7 +2,7 @@
// Licensed under the MIT License.
import * as fsapi from "fs-extra"
import { Disposable, env, LogOutputChannel } from "vscode"
import { Disposable, env, LogOutputChannel, workspace } from "vscode"
import { State } from "vscode-languageclient"
import {
LanguageClient,
@@ -24,6 +24,13 @@ import { isVirtualWorkspace } from "./vscodeapi"
export type IInitOptions = { settings: ISettings[]; globalSettings: ISettings }
let _disposables: Disposable[] = []
export function disposeServerResources(): void {
_disposables.forEach((disposable) => disposable.dispose())
_disposables = []
}
async function createServer(
settings: ISettings,
serverId: string,
@@ -63,6 +70,7 @@ async function createServer(
}
// Options to control the language client
const tclFileWatcher = workspace.createFileSystemWatcher("**/*.tcl")
const clientOptions: LanguageClientOptions = {
// Register the server for python documents
documentSelector: isVirtualWorkspace()
@@ -76,13 +84,16 @@ async function createServer(
outputChannel: outputChannel,
traceOutputChannel: outputChannel,
revealOutputChannelOn: RevealOutputChannelOn.Never,
synchronize: {
fileEvents: tclFileWatcher
},
initializationOptions
}
_disposables.push(tclFileWatcher)
return new LanguageClient(serverId, serverName, serverOptions, clientOptions)
}
let _disposables: Disposable[] = []
export async function restartServer(
serverId: string,
serverName: string,
@@ -92,8 +103,7 @@ export async function restartServer(
if (lsClient) {
traceInfo(`Server: Stop requested`)
await lsClient.stop()
_disposables.forEach((d) => d.dispose())
_disposables = []
disposeServerResources()
}
const projectRoot = await getProjectRoot()
const workspaceSetting = await getWorkspaceSettings(serverId, projectRoot, true)
@@ -122,6 +132,7 @@ export async function restartServer(
await newLSClient.start()
} catch (ex) {
traceError(`Server: Start failed: ${ex}`)
disposeServerResources()
return undefined
}