From e5e25c66ca4e1fbd0ebadee3a14890758dc06c6f Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sat, 16 Nov 2024 23:05:19 -0500 Subject: [PATCH] Guarantee that ClangdContext.client is null The code is reorganized slightly so that in the cases where the client would be null, we don't create a ClangdContext object in the first place --- src/clangd-context.ts | 24 ++++++++++++++++-------- src/extension.ts | 22 +++++++++++++--------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/clangd-context.ts b/src/clangd-context.ts index 05248ea..7b62da2 100644 --- a/src/clangd-context.ts +++ b/src/clangd-context.ts @@ -56,19 +56,27 @@ class EnableEditsNearCursorFeature implements vscodelc.StaticFeature { dispose() {} } +export async function createContext(globalStoragePath: string, + outputChannel: vscode.OutputChannel): Promise { + const subscriptions: vscode.Disposable[] = []; + const clangdPath = await install.activate(subscriptions, globalStoragePath); + if (!clangdPath) + return null; + + const clangdArguments = await config.get('arguments'); + + return new ClangdContext(clangdPath, clangdArguments, outputChannel); +} + export class ClangdContext implements vscode.Disposable { subscriptions: vscode.Disposable[] = []; - client!: ClangdLanguageClient; - - async activate(globalStoragePath: string, - outputChannel: vscode.OutputChannel) { - const clangdPath = await install.activate(this.subscriptions, globalStoragePath); - if (!clangdPath) - return; + client: ClangdLanguageClient; + constructor(clangdPath: string, clangdArguments: string[], + outputChannel: vscode.OutputChannel) { const clangd: vscodelc.Executable = { command: clangdPath, - args: await config.get('arguments'), + args: clangdArguments, options: {cwd: vscode.workspace.rootPath || process.cwd()} }; const traceFile = config.get('trace'); diff --git a/src/extension.ts b/src/extension.ts index fb9370a..cf279e9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -3,7 +3,7 @@ import * as vscode from 'vscode'; import {ClangdExtension} from '../api/vscode-clangd'; import {ClangdExtensionImpl} from './api'; -import {ClangdContext} from './clangd-context'; +import {ClangdContext, createContext} from './clangd-context'; let apiInstance: ClangdExtensionImpl|undefined; @@ -16,8 +16,7 @@ export async function activate(context: vscode.ExtensionContext): const outputChannel = vscode.window.createOutputChannel('clangd'); context.subscriptions.push(outputChannel); - const clangdContext = new ClangdContext; - context.subscriptions.push(clangdContext); + let clangdContext: ClangdContext | null = null; // An empty place holder for the activate command, otherwise we'll get an // "command is not registered" error. @@ -31,20 +30,25 @@ export async function activate(context: vscode.ExtensionContext): // stop/start cycle in this situation is pointless, and doesn't work // anyways because the client can't be stop()-ped when it's still in the // Starting state). - if (clangdContext.clientIsStarting()) { + if (clangdContext && clangdContext.clientIsStarting()) { return; } - await clangdContext.dispose(); - await clangdContext.activate(context.globalStoragePath, outputChannel); + if (clangdContext) + await clangdContext.dispose(); + clangdContext = await createContext(context.globalStoragePath, outputChannel); + if (clangdContext) + context.subscriptions.push(clangdContext); if (apiInstance) { - apiInstance.client = clangdContext.client; + apiInstance.client = clangdContext!.client; } })); let shouldCheck = false; if (vscode.workspace.getConfiguration('clangd').get('enable')) { - await clangdContext.activate(context.globalStoragePath, outputChannel); + clangdContext = await createContext(context.globalStoragePath, outputChannel); + if (clangdContext) + context.subscriptions.push(clangdContext); shouldCheck = vscode.workspace.getConfiguration('clangd').get( 'detectExtensionConflicts') ?? @@ -83,6 +87,6 @@ export async function activate(context: vscode.ExtensionContext): }, 5000); } - apiInstance = new ClangdExtensionImpl(clangdContext.client); + apiInstance = new ClangdExtensionImpl(clangdContext!.client); return apiInstance; }