Unnamed repository; edit this file 'description' to name the repository.
Properly reload changed configs for server start
Lukas Wirth 2022-10-17
parent 6f43597 · commit 8aaafdd
-rw-r--r--editors/code/src/commands.ts4
-rw-r--r--editors/code/src/config.ts4
-rw-r--r--editors/code/src/ctx.ts58
-rw-r--r--editors/code/src/main.ts42
4 files changed, 51 insertions, 57 deletions
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index cbdeb28c99..cb088fc6c6 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -310,6 +310,10 @@ export function ssr(ctx: Ctx): Cmd {
export function serverVersion(ctx: Ctx): Cmd {
return async () => {
+ if (!ctx.serverPath) {
+ void vscode.window.showWarningMessage(`rust-analyzer server is not running`);
+ return;
+ }
const { stdout } = spawnSync(ctx.serverPath, ["--version"], { encoding: "utf8" });
const versionString = stdout.slice(`rust-analyzer `.length).trim();
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index 199db6e30f..10e243dc89 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -14,8 +14,6 @@ export class Config {
readonly rootSection = "rust-analyzer";
private readonly requiresWorkspaceReloadOpts = [
- "serverPath",
- "server",
// FIXME: This shouldn't be here, changing this setting should reload
// `continueCommentsOnNewline` behavior without restart
"typing",
@@ -23,6 +21,8 @@ export class Config {
private readonly requiresReloadOpts = [
"cargo",
"procMacro",
+ "serverPath",
+ "server",
"files",
"lens", // works as lens.*
]
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts
index d4f5ab3c88..f62ccd1a65 100644
--- a/editors/code/src/ctx.ts
+++ b/editors/code/src/ctx.ts
@@ -6,6 +6,8 @@ import { Config, substituteVariablesInEnv, substituteVSCodeVariables } from "./c
import { createClient } from "./client";
import { isRustEditor, log, RustEditor } from "./util";
import { ServerStatusParams } from "./lsp_ext";
+import { PersistentState } from "./persistent_state";
+import { bootstrap } from "./bootstrap";
export type Workspace =
| {
@@ -17,28 +19,18 @@ export type Workspace =
};
export class Ctx {
- private client: lc.LanguageClient | undefined;
- readonly config: Config;
- serverPath: string;
readonly statusBar: vscode.StatusBarItem;
+ readonly config: Config;
+
+ private client: lc.LanguageClient | undefined;
traceOutputChannel: vscode.OutputChannel | undefined;
outputChannel: vscode.OutputChannel | undefined;
-
- serverOptions:
- | {
- run: lc.Executable;
- debug: lc.Executable;
- }
- | undefined;
workspace: Workspace;
+ state: PersistentState;
+ serverPath: string | undefined;
- constructor(
- readonly extCtx: vscode.ExtensionContext,
- config: Config,
- serverPath: string,
- workspace: Workspace
- ) {
+ constructor(readonly extCtx: vscode.ExtensionContext, workspace: Workspace) {
this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
extCtx.subscriptions.push(this.statusBar);
extCtx.subscriptions.push({
@@ -50,9 +42,10 @@ export class Ctx {
this.statusBar.tooltip = "ready";
this.statusBar.command = "rust-analyzer.analyzerStatus";
this.statusBar.show();
- this.serverPath = serverPath;
- this.config = config;
this.workspace = workspace;
+
+ this.state = new PersistentState(extCtx.globalState);
+ this.config = new Config(extCtx);
}
clientFetcher() {
@@ -64,6 +57,7 @@ export class Ctx {
}
async getClient() {
+ // if server path changes -> dispose
if (!this.traceOutputChannel) {
this.traceOutputChannel = vscode.window.createOutputChannel(
"Rust Analyzer Language Server Trace"
@@ -72,8 +66,20 @@ export class Ctx {
if (!this.outputChannel) {
this.outputChannel = vscode.window.createOutputChannel("Rust Analyzer Language Server");
}
- if (!this.serverOptions) {
- log.info("Creating server options client");
+
+ if (!this.client) {
+ log.info("Creating language client");
+
+ this.serverPath = await bootstrap(this.extCtx, this.config, this.state).catch((err) => {
+ let message = "bootstrap error. ";
+
+ message +=
+ 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). ';
+ message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }';
+
+ log.error("Bootstrap error", err);
+ throw new Error(message);
+ });
const newEnv = substituteVariablesInEnv(
Object.assign({}, process.env, this.config.serverExtraEnv)
);
@@ -81,16 +87,11 @@ export class Ctx {
command: this.serverPath,
options: { env: newEnv },
};
- this.serverOptions = {
+ const serverOptions = {
run,
debug: run,
};
- } else {
- this.serverOptions.run.command = this.serverPath;
- this.serverOptions.debug.command = this.serverPath;
- }
- if (!this.client) {
- log.info("Creating language client");
+
let rawInitializationOptions = vscode.workspace.getConfiguration("rust-analyzer");
if (this.workspace.kind === "Detached Files") {
@@ -106,7 +107,7 @@ export class Ctx {
this.traceOutputChannel,
this.outputChannel,
initializationOptions,
- this.serverOptions
+ serverOptions
);
this.client.onNotification(ra.serverStatus, (params) => this.setServerStatus(params));
}
@@ -128,6 +129,7 @@ export class Ctx {
async disposeClient() {
log.info("Deactivating language client");
await this.client?.dispose();
+ this.serverPath = undefined;
this.client = undefined;
}
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 4ff27e0b55..84f0a5810f 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -3,12 +3,9 @@ import * as lc from "vscode-languageclient/node";
import * as commands from "./commands";
import { Ctx, Workspace } from "./ctx";
-import { log, isRustDocument } from "./util";
-import { PersistentState } from "./persistent_state";
+import { isRustDocument } from "./util";
import { activateTaskProvider } from "./tasks";
import { setContextValue } from "./util";
-import { bootstrap } from "./bootstrap";
-import { Config } from "./config";
const RUST_PROJECT_CONTEXT_NAME = "inRustProject";
@@ -56,24 +53,13 @@ export async function activate(
}
: { kind: "Workspace Folder" };
- const state = new PersistentState(context.globalState);
- const config = new Config(context);
-
- const serverPath = await bootstrap(context, config, state).catch((err) => {
- let message = "bootstrap error. ";
-
- message += 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). ';
- message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }';
-
- log.error("Bootstrap error", err);
- throw new Error(message);
- });
-
- const ctx = new Ctx(context, config, serverPath, workspace);
+ const ctx = new Ctx(context, workspace);
// VS Code doesn't show a notification when an extension fails to activate
// so we do it ourselves.
return await activateServer(ctx).catch((err) => {
- void vscode.window.showErrorMessage(`Cannot activate rust-analyzer: ${err.message}`);
+ void vscode.window.showErrorMessage(
+ `Cannot activate rust-analyzer extension: ${err.message}`
+ );
throw err;
});
}
@@ -83,7 +69,6 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
ctx.pushExtCleanup(activateTaskProvider(ctx.config));
}
- await ctx.activate();
await initCommonContext(ctx);
if (ctx.config.typingContinueCommentsOnNewline) {
@@ -91,17 +76,19 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
}
vscode.workspace.onDidChangeConfiguration(
- (_) =>
- ctx
- .getClient()
- .then((it) =>
- it.sendNotification("workspace/didChangeConfiguration", { settings: "" })
- )
- .catch(log.error),
+ async (_) => {
+ await ctx
+ .clientFetcher()
+ .client?.sendNotification("workspace/didChangeConfiguration", { settings: "" });
+ },
null,
ctx.subscriptions
);
+ await ctx.activate().catch((err) => {
+ void vscode.window.showErrorMessage(`Cannot activate rust-analyzer server: ${err.message}`);
+ });
+
return ctx.clientFetcher();
}
@@ -130,6 +117,7 @@ async function initCommonContext(ctx: Ctx) {
// Commands which invokes manually via command palette, shortcut, etc.
ctx.registerCommand("reload", (_) => async () => {
void vscode.window.showInformationMessage("Reloading rust-analyzer...");
+ // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed
await ctx.disposeClient();
await ctx.activate();
});