From a8e0a20ce4396d3c77adf3b5deb48edfd27d6af2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 20 Oct 2022 21:12:58 +0200 Subject: [PATCH] internal: Properly handle language configuration config changes --- editors/code/src/config.ts | 100 ++++++++++++++++++++++++++++--------- editors/code/src/ctx.ts | 8 ++- editors/code/src/main.ts | 60 ++-------------------- 3 files changed, 88 insertions(+), 80 deletions(-) diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 10e243dc896..61125d7a83e 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -11,13 +11,9 @@ export type RunnableEnvCfg = export class Config { readonly extensionId = "rust-lang.rust-analyzer"; + configureLang: vscode.Disposable | undefined; readonly rootSection = "rust-analyzer"; - private readonly requiresWorkspaceReloadOpts = [ - // FIXME: This shouldn't be here, changing this setting should reload - // `continueCommentsOnNewline` behavior without restart - "typing", - ].map((opt) => `${this.rootSection}.${opt}`); private readonly requiresReloadOpts = [ "cargo", "procMacro", @@ -25,9 +21,7 @@ export class Config { "server", "files", "lens", // works as lens.* - ] - .map((opt) => `${this.rootSection}.${opt}`) - .concat(this.requiresWorkspaceReloadOpts); + ].map((opt) => `${this.rootSection}.${opt}`); readonly package: { version: string; @@ -45,6 +39,11 @@ export class Config { ctx.subscriptions ); this.refreshLogging(); + this.configureLanguage(); + } + + dispose() { + this.configureLang?.dispose(); } private refreshLogging() { @@ -58,33 +57,86 @@ export class Config { private async onDidChangeConfiguration(event: vscode.ConfigurationChangeEvent) { this.refreshLogging(); + this.configureLanguage(); + const requiresReloadOpt = this.requiresReloadOpts.find((opt) => event.affectsConfiguration(opt) ); if (!requiresReloadOpt) return; - const requiresWorkspaceReloadOpt = this.requiresWorkspaceReloadOpts.find((opt) => - event.affectsConfiguration(opt) - ); - - if (!requiresWorkspaceReloadOpt && this.restartServerOnConfigChange) { + if (this.restartServerOnConfigChange) { await vscode.commands.executeCommand("rust-analyzer.reload"); return; } - const message = requiresWorkspaceReloadOpt - ? `Changing "${requiresWorkspaceReloadOpt}" requires a window reload` - : `Changing "${requiresReloadOpt}" requires a reload`; - const userResponse = await vscode.window.showInformationMessage(message, "Reload now"); + const message = `Changing "${requiresReloadOpt}" requires a server restart`; + const userResponse = await vscode.window.showInformationMessage(message, "Restart now"); - if (userResponse === "Reload now") { - const command = requiresWorkspaceReloadOpt - ? "workbench.action.reloadWindow" - : "rust-analyzer.reload"; - if (userResponse === "Reload now") { - await vscode.commands.executeCommand(command); - } + if (userResponse) { + const command = "rust-analyzer.reload"; + await vscode.commands.executeCommand(command); + } + } + + /** + * Sets up additional language configuration that's impossible to do via a + * separate language-configuration.json file. See [1] for more information. + * + * [1]: https://github.com/Microsoft/vscode/issues/11514#issuecomment-244707076 + */ + private configureLanguage() { + if (this.typingContinueCommentsOnNewline && !this.configureLang) { + const indentAction = vscode.IndentAction.None; + + this.configureLang = vscode.languages.setLanguageConfiguration("rust", { + onEnterRules: [ + { + // Doc single-line comment + // e.g. ///| + beforeText: /^\s*\/{3}.*$/, + action: { indentAction, appendText: "/// " }, + }, + { + // Parent doc single-line comment + // e.g. //!| + beforeText: /^\s*\/{2}\!.*$/, + action: { indentAction, appendText: "//! " }, + }, + { + // Begins an auto-closed multi-line comment (standard or parent doc) + // e.g. /** | */ or /*! | */ + beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/, + afterText: /^\s*\*\/$/, + action: { + indentAction: vscode.IndentAction.IndentOutdent, + appendText: " * ", + }, + }, + { + // Begins a multi-line comment (standard or parent doc) + // e.g. /** ...| or /*! ...| + beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/, + action: { indentAction, appendText: " * " }, + }, + { + // Continues a multi-line comment + // e.g. * ...| + beforeText: /^(\ \ )*\ \*(\ ([^\*]|\*(?!\/))*)?$/, + action: { indentAction, appendText: "* " }, + }, + { + // Dedents after closing a multi-line comment + // e.g. */| + beforeText: /^(\ \ )*\ \*\/\s*$/, + action: { indentAction, removeText: 1 }, + }, + ], + }); + } + if (!this.typingContinueCommentsOnNewline && this.configureLang) { + this.configureLang.dispose(); + this.configureLang = undefined; } } diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index e94d4365c37..75c6d4698c1 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -38,6 +38,7 @@ export class Ctx { this.dispose(); }, }); + extCtx.subscriptions.push(this); this.statusBar.text = "rust-analyzer"; this.statusBar.tooltip = "ready"; this.statusBar.command = "rust-analyzer.analyzerStatus"; @@ -48,10 +49,15 @@ export class Ctx { this.config = new Config(extCtx); } + dispose() { + this.config.dispose(); + } + clientFetcher() { + const self = this; return { get client(): lc.LanguageClient | undefined { - return this.client; + return self.client; }, }; } diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index c47680fbac5..fa7dc6fe304 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -77,10 +77,6 @@ async function activateServer(ctx: Ctx): Promise { await initCommonContext(ctx); - if (ctx.config.typingContinueCommentsOnNewline) { - ctx.pushExtCleanup(configureLanguage()); - } - vscode.workspace.onDidChangeConfiguration( async (_) => { await ctx @@ -129,6 +125,11 @@ async function initCommonContext(ctx: Ctx) { ctx.registerCommand("stopServer", (_) => async () => { // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed await ctx.disposeClient(); + ctx.setServerStatus({ + health: "ok", + quiescent: true, + message: "server is not running", + }); }); ctx.registerCommand("analyzerStatus", commands.analyzerStatus); ctx.registerCommand("memoryUsage", commands.memoryUsage); @@ -172,54 +173,3 @@ async function initCommonContext(ctx: Ctx) { defaultOnEnter.dispose(); ctx.registerCommand("onEnter", commands.onEnter); } - -/** - * Sets up additional language configuration that's impossible to do via a - * separate language-configuration.json file. See [1] for more information. - * - * [1]: https://github.com/Microsoft/vscode/issues/11514#issuecomment-244707076 - */ -function configureLanguage(): vscode.Disposable { - const indentAction = vscode.IndentAction.None; - return vscode.languages.setLanguageConfiguration("rust", { - onEnterRules: [ - { - // Doc single-line comment - // e.g. ///| - beforeText: /^\s*\/{3}.*$/, - action: { indentAction, appendText: "/// " }, - }, - { - // Parent doc single-line comment - // e.g. //!| - beforeText: /^\s*\/{2}\!.*$/, - action: { indentAction, appendText: "//! " }, - }, - { - // Begins an auto-closed multi-line comment (standard or parent doc) - // e.g. /** | */ or /*! | */ - beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/, - afterText: /^\s*\*\/$/, - action: { indentAction: vscode.IndentAction.IndentOutdent, appendText: " * " }, - }, - { - // Begins a multi-line comment (standard or parent doc) - // e.g. /** ...| or /*! ...| - beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/, - action: { indentAction, appendText: " * " }, - }, - { - // Continues a multi-line comment - // e.g. * ...| - beforeText: /^(\ \ )*\ \*(\ ([^\*]|\*(?!\/))*)?$/, - action: { indentAction, appendText: "* " }, - }, - { - // Dedents after closing a multi-line comment - // e.g. */| - beforeText: /^(\ \ )*\ \*\/\s*$/, - action: { indentAction, removeText: 1 }, - }, - ], - }); -}