From aea18cb6582e6e51fe2e3d4c82db89636a647697 Mon Sep 17 00:00:00 2001 From: Ben McMorran Date: Tue, 8 Apr 2025 17:10:19 -0700 Subject: [PATCH] Shutdown LSP server on request --- Extension/src/LanguageServer/client.ts | 27 +++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 44255921e..72c2a6947 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -89,7 +89,7 @@ export function hasTrustedCompilerPaths(): boolean { // Data shared by all clients. let languageClient: LanguageClient; -let firstClientStarted: Promise; +let firstClientStarted: Promise<{ wasShutdown: boolean }>; let languageClientCrashedNeedsRestart: boolean = false; const languageClientCrashTimes: number[] = []; let compilerDefaults: configs.CompilerDefaults | undefined; @@ -508,6 +508,10 @@ interface CppInitializationParams { settings: SettingsParams; } +interface CppInitializationResult { + shouldShutdown: boolean; +} + interface TagParseStatus { localizeStringParams: LocalizeStringParams; isPaused: boolean; @@ -585,7 +589,7 @@ export interface CopilotCompletionContextParams { // Requests const PreInitializationRequest: RequestType = new RequestType('cpptools/preinitialize'); -const InitializationRequest: RequestType = new RequestType('cpptools/initialize'); +const InitializationRequest: RequestType = new RequestType('cpptools/initialize'); const QueryCompilerDefaultsRequest: RequestType = new RequestType('cpptools/queryCompilerDefaults'); const SwitchHeaderSourceRequest: RequestType = new RequestType('cpptools/didSwitchHeaderSource'); const GetDiagnosticsRequest: RequestType = new RequestType('cpptools/getDiagnostics'); @@ -1310,7 +1314,12 @@ export class DefaultClient implements Client { private async init(rootUri: vscode.Uri | undefined, isFirstClient: boolean) { ui = getUI(); ui.bind(this); - await firstClientStarted; + if ((await firstClientStarted).wasShutdown) { + this.isSupported = false; + DefaultClient.isStarted.resolve(); + return; + } + try { const workspaceFolder: vscode.WorkspaceFolder | undefined = this.rootFolder; this.innerConfiguration = new configs.CppProperties(this, rootUri, workspaceFolder); @@ -1580,7 +1589,7 @@ export class DefaultClient implements Client { }; } - private async createLanguageClient(): Promise { + private async createLanguageClient(): Promise<{ wasShutdown: boolean }> { this.currentCaseSensitiveFileSupport = new PersistentWorkspaceState("CPP.currentCaseSensitiveFileSupport", false); let resetDatabase: boolean = false; const serverModule: string = getLanguageServerFileName(); @@ -1713,7 +1722,15 @@ export class DefaultClient implements Client { // Move initialization to a separate message, so we can see log output from it. // A request is used in order to wait for completion and ensure that no subsequent // higher priority message may be processed before the Initialization request. - await languageClient.sendRequest(InitializationRequest, cppInitializationParams); + const initializeResult = await languageClient.sendRequest(InitializationRequest, cppInitializationParams); + + // If the server requested shutdown, then reload with the failsafe (null) client. + if (initializeResult.shouldShutdown) { + await languageClient.stop(); + await clients.recreateClients(true); + } + + return { wasShutdown: initializeResult.shouldShutdown }; } public async sendDidChangeSettings(): Promise {