Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'editors/code/src/ctx.ts')
| -rw-r--r-- | editors/code/src/ctx.ts | 67 |
1 files changed, 60 insertions, 7 deletions
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index d198d4e938..3e366525ee 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -4,11 +4,15 @@ import * as ra from "./lsp_ext"; import { Config, substituteVariablesInEnv, substituteVSCodeVariables } from "./config"; import { createClient } from "./client"; -import { isRustEditor, log, RustEditor } from "./util"; +import { isRustDocument, isRustEditor, log, RustEditor } from "./util"; import { ServerStatusParams } from "./lsp_ext"; import { PersistentState } from "./persistent_state"; import { bootstrap } from "./bootstrap"; +// We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if +// only those are in use. We use "Empty" to represent these scenarios +// (r-a still somewhat works with Live Share, because commands are tunneled to the host) + export type Workspace = | { kind: "Empty" } | { @@ -19,6 +23,24 @@ export type Workspace = files: vscode.TextDocument[]; }; +export function fetchWorkspace(): Workspace { + const folders = (vscode.workspace.workspaceFolders || []).filter( + (folder) => folder.uri.scheme === "file" + ); + const rustDocuments = vscode.workspace.textDocuments.filter((document) => + isRustDocument(document) + ); + + return folders.length === 0 + ? rustDocuments.length === 0 + ? { kind: "Empty" } + : { + kind: "Detached Files", + files: rustDocuments, + } + : { kind: "Workspace Folder" }; +} + export type CommandFactory = { enabled: (ctx: CtxInit) => Cmd; disabled?: (ctx: Ctx) => Cmd; @@ -75,6 +97,31 @@ export class Ctx { this.commandDisposables.forEach((disposable) => disposable.dispose()); } + async onWorkspaceFolderChanges() { + const workspace = fetchWorkspace(); + if (workspace.kind === "Detached Files" && this.workspace.kind === "Detached Files") { + if (workspace.files !== this.workspace.files) { + if (this.client?.isRunning()) { + // Ideally we wouldn't need to tear down the server here, but currently detached files + // are only specified at server start + await this.stopAndDispose(); + await this.start(); + } + return; + } + } + if (workspace.kind === "Workspace Folder" && this.workspace.kind === "Workspace Folder") { + return; + } + if (workspace.kind === "Empty") { + await this.stopAndDispose(); + return; + } + if (this.client?.isRunning()) { + await this.restart(); + } + } + private async getOrCreateClient() { if (this.workspace.kind === "Empty") { return; @@ -143,8 +190,8 @@ export class Ctx { return this._client; } - async activate() { - log.info("Activating language client"); + async start() { + log.info("Starting language client"); const client = await this.getOrCreateClient(); if (!client) { return; @@ -153,20 +200,26 @@ export class Ctx { this.updateCommands(); } - async deactivate() { + async restart() { + // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed + await this.stopAndDispose(); + await this.start(); + } + + async stop() { if (!this._client) { return; } - log.info("Deactivating language client"); + log.info("Stopping language client"); this.updateCommands("disable"); await this._client.stop(); } - async stop() { + async stopAndDispose() { if (!this._client) { return; } - log.info("Stopping language client"); + log.info("Disposing language client"); this.updateCommands("disable"); await this.disposeClient(); } |