@@ -4,11 +4,15 @@ import * as ra from "./lsp_ext";
44
55import { Config , substituteVariablesInEnv , substituteVSCodeVariables } from "./config" ;
66import { createClient } from "./client" ;
7- import { isRustEditor , log , RustEditor } from "./util" ;
7+ import { isRustDocument , isRustEditor , log , RustEditor } from "./util" ;
88import { ServerStatusParams } from "./lsp_ext" ;
99import { PersistentState } from "./persistent_state" ;
1010import { bootstrap } from "./bootstrap" ;
1111
12+ // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if
13+ // only those are in use. We use "Empty" to represent these scenarios
14+ // (r-a still somewhat works with Live Share, because commands are tunneled to the host)
15+
1216export type Workspace =
1317 | { kind : "Empty" }
1418 | {
@@ -19,6 +23,24 @@ export type Workspace =
1923 files : vscode . TextDocument [ ] ;
2024 } ;
2125
26+ export function fetchWorkspace ( ) : Workspace {
27+ const folders = ( vscode . workspace . workspaceFolders || [ ] ) . filter (
28+ ( folder ) => folder . uri . scheme === "file"
29+ ) ;
30+ const rustDocuments = vscode . workspace . textDocuments . filter ( ( document ) =>
31+ isRustDocument ( document )
32+ ) ;
33+
34+ return folders . length === 0
35+ ? rustDocuments . length === 0
36+ ? { kind : "Empty" }
37+ : {
38+ kind : "Detached Files" ,
39+ files : rustDocuments ,
40+ }
41+ : { kind : "Workspace Folder" } ;
42+ }
43+
2244export type CommandFactory = {
2345 enabled : ( ctx : CtxInit ) => Cmd ;
2446 disabled ?: ( ctx : Ctx ) => Cmd ;
@@ -75,6 +97,31 @@ export class Ctx {
7597 this . commandDisposables . forEach ( ( disposable ) => disposable . dispose ( ) ) ;
7698 }
7799
100+ async onWorkspaceFolderChanges ( ) {
101+ const workspace = fetchWorkspace ( ) ;
102+ if ( workspace . kind === "Detached Files" && this . workspace . kind === "Detached Files" ) {
103+ if ( workspace . files !== this . workspace . files ) {
104+ if ( this . client ?. isRunning ( ) ) {
105+ // Ideally we wouldn't need to tear down the server here, but currently detached files
106+ // are only specified at server start
107+ await this . stopAndDispose ( ) ;
108+ await this . start ( ) ;
109+ }
110+ return ;
111+ }
112+ }
113+ if ( workspace . kind === "Workspace Folder" && this . workspace . kind === "Workspace Folder" ) {
114+ return ;
115+ }
116+ if ( workspace . kind === "Empty" ) {
117+ await this . stopAndDispose ( ) ;
118+ return ;
119+ }
120+ if ( this . client ?. isRunning ( ) ) {
121+ await this . restart ( ) ;
122+ }
123+ }
124+
78125 private async getOrCreateClient ( ) {
79126 if ( this . workspace . kind === "Empty" ) {
80127 return ;
@@ -143,8 +190,8 @@ export class Ctx {
143190 return this . _client ;
144191 }
145192
146- async activate ( ) {
147- log . info ( "Activating language client" ) ;
193+ async start ( ) {
194+ log . info ( "Starting language client" ) ;
148195 const client = await this . getOrCreateClient ( ) ;
149196 if ( ! client ) {
150197 return ;
@@ -153,20 +200,26 @@ export class Ctx {
153200 this . updateCommands ( ) ;
154201 }
155202
156- async deactivate ( ) {
203+ async restart ( ) {
204+ // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed
205+ await this . stopAndDispose ( ) ;
206+ await this . start ( ) ;
207+ }
208+
209+ async stop ( ) {
157210 if ( ! this . _client ) {
158211 return ;
159212 }
160- log . info ( "Deactivating language client" ) ;
213+ log . info ( "Stopping language client" ) ;
161214 this . updateCommands ( "disable" ) ;
162215 await this . _client . stop ( ) ;
163216 }
164217
165- async stop ( ) {
218+ async stopAndDispose ( ) {
166219 if ( ! this . _client ) {
167220 return ;
168221 }
169- log . info ( "Stopping language client" ) ;
222+ log . info ( "Disposing language client" ) ;
170223 this . updateCommands ( "disable" ) ;
171224 await this . disposeClient ( ) ;
172225 }
0 commit comments