Skip to content

Commit 8aaafdd

Browse files
committed
Properly reload changed configs for server start
1 parent 6f43597 commit 8aaafdd

File tree

4 files changed

+51
-57
lines changed

4 files changed

+51
-57
lines changed

editors/code/src/commands.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,10 @@ export function ssr(ctx: Ctx): Cmd {
310310

311311
export function serverVersion(ctx: Ctx): Cmd {
312312
return async () => {
313+
if (!ctx.serverPath) {
314+
void vscode.window.showWarningMessage(`rust-analyzer server is not running`);
315+
return;
316+
}
313317
const { stdout } = spawnSync(ctx.serverPath, ["--version"], { encoding: "utf8" });
314318
const versionString = stdout.slice(`rust-analyzer `.length).trim();
315319

editors/code/src/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ export class Config {
1414

1515
readonly rootSection = "rust-analyzer";
1616
private readonly requiresWorkspaceReloadOpts = [
17-
"serverPath",
18-
"server",
1917
// FIXME: This shouldn't be here, changing this setting should reload
2018
// `continueCommentsOnNewline` behavior without restart
2119
"typing",
2220
].map((opt) => `${this.rootSection}.${opt}`);
2321
private readonly requiresReloadOpts = [
2422
"cargo",
2523
"procMacro",
24+
"serverPath",
25+
"server",
2626
"files",
2727
"lens", // works as lens.*
2828
]

editors/code/src/ctx.ts

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { Config, substituteVariablesInEnv, substituteVSCodeVariables } from "./c
66
import { createClient } from "./client";
77
import { isRustEditor, log, RustEditor } from "./util";
88
import { ServerStatusParams } from "./lsp_ext";
9+
import { PersistentState } from "./persistent_state";
10+
import { bootstrap } from "./bootstrap";
911

1012
export type Workspace =
1113
| {
@@ -17,28 +19,18 @@ export type Workspace =
1719
};
1820

1921
export class Ctx {
20-
private client: lc.LanguageClient | undefined;
21-
readonly config: Config;
22-
serverPath: string;
2322
readonly statusBar: vscode.StatusBarItem;
23+
readonly config: Config;
24+
25+
private client: lc.LanguageClient | undefined;
2426

2527
traceOutputChannel: vscode.OutputChannel | undefined;
2628
outputChannel: vscode.OutputChannel | undefined;
27-
28-
serverOptions:
29-
| {
30-
run: lc.Executable;
31-
debug: lc.Executable;
32-
}
33-
| undefined;
3429
workspace: Workspace;
30+
state: PersistentState;
31+
serverPath: string | undefined;
3532

36-
constructor(
37-
readonly extCtx: vscode.ExtensionContext,
38-
config: Config,
39-
serverPath: string,
40-
workspace: Workspace
41-
) {
33+
constructor(readonly extCtx: vscode.ExtensionContext, workspace: Workspace) {
4234
this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
4335
extCtx.subscriptions.push(this.statusBar);
4436
extCtx.subscriptions.push({
@@ -50,9 +42,10 @@ export class Ctx {
5042
this.statusBar.tooltip = "ready";
5143
this.statusBar.command = "rust-analyzer.analyzerStatus";
5244
this.statusBar.show();
53-
this.serverPath = serverPath;
54-
this.config = config;
5545
this.workspace = workspace;
46+
47+
this.state = new PersistentState(extCtx.globalState);
48+
this.config = new Config(extCtx);
5649
}
5750

5851
clientFetcher() {
@@ -64,6 +57,7 @@ export class Ctx {
6457
}
6558

6659
async getClient() {
60+
// if server path changes -> dispose
6761
if (!this.traceOutputChannel) {
6862
this.traceOutputChannel = vscode.window.createOutputChannel(
6963
"Rust Analyzer Language Server Trace"
@@ -72,25 +66,32 @@ export class Ctx {
7266
if (!this.outputChannel) {
7367
this.outputChannel = vscode.window.createOutputChannel("Rust Analyzer Language Server");
7468
}
75-
if (!this.serverOptions) {
76-
log.info("Creating server options client");
69+
70+
if (!this.client) {
71+
log.info("Creating language client");
72+
73+
this.serverPath = await bootstrap(this.extCtx, this.config, this.state).catch((err) => {
74+
let message = "bootstrap error. ";
75+
76+
message +=
77+
'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). ';
78+
message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }';
79+
80+
log.error("Bootstrap error", err);
81+
throw new Error(message);
82+
});
7783
const newEnv = substituteVariablesInEnv(
7884
Object.assign({}, process.env, this.config.serverExtraEnv)
7985
);
8086
const run: lc.Executable = {
8187
command: this.serverPath,
8288
options: { env: newEnv },
8389
};
84-
this.serverOptions = {
90+
const serverOptions = {
8591
run,
8692
debug: run,
8793
};
88-
} else {
89-
this.serverOptions.run.command = this.serverPath;
90-
this.serverOptions.debug.command = this.serverPath;
91-
}
92-
if (!this.client) {
93-
log.info("Creating language client");
94+
9495
let rawInitializationOptions = vscode.workspace.getConfiguration("rust-analyzer");
9596

9697
if (this.workspace.kind === "Detached Files") {
@@ -106,7 +107,7 @@ export class Ctx {
106107
this.traceOutputChannel,
107108
this.outputChannel,
108109
initializationOptions,
109-
this.serverOptions
110+
serverOptions
110111
);
111112
this.client.onNotification(ra.serverStatus, (params) => this.setServerStatus(params));
112113
}
@@ -128,6 +129,7 @@ export class Ctx {
128129
async disposeClient() {
129130
log.info("Deactivating language client");
130131
await this.client?.dispose();
132+
this.serverPath = undefined;
131133
this.client = undefined;
132134
}
133135

editors/code/src/main.ts

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@ import * as lc from "vscode-languageclient/node";
33

44
import * as commands from "./commands";
55
import { Ctx, Workspace } from "./ctx";
6-
import { log, isRustDocument } from "./util";
7-
import { PersistentState } from "./persistent_state";
6+
import { isRustDocument } from "./util";
87
import { activateTaskProvider } from "./tasks";
98
import { setContextValue } from "./util";
10-
import { bootstrap } from "./bootstrap";
11-
import { Config } from "./config";
129

1310
const RUST_PROJECT_CONTEXT_NAME = "inRustProject";
1411

@@ -56,24 +53,13 @@ export async function activate(
5653
}
5754
: { kind: "Workspace Folder" };
5855

59-
const state = new PersistentState(context.globalState);
60-
const config = new Config(context);
61-
62-
const serverPath = await bootstrap(context, config, state).catch((err) => {
63-
let message = "bootstrap error. ";
64-
65-
message += 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). ';
66-
message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }';
67-
68-
log.error("Bootstrap error", err);
69-
throw new Error(message);
70-
});
71-
72-
const ctx = new Ctx(context, config, serverPath, workspace);
56+
const ctx = new Ctx(context, workspace);
7357
// VS Code doesn't show a notification when an extension fails to activate
7458
// so we do it ourselves.
7559
return await activateServer(ctx).catch((err) => {
76-
void vscode.window.showErrorMessage(`Cannot activate rust-analyzer: ${err.message}`);
60+
void vscode.window.showErrorMessage(
61+
`Cannot activate rust-analyzer extension: ${err.message}`
62+
);
7763
throw err;
7864
});
7965
}
@@ -83,25 +69,26 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
8369
ctx.pushExtCleanup(activateTaskProvider(ctx.config));
8470
}
8571

86-
await ctx.activate();
8772
await initCommonContext(ctx);
8873

8974
if (ctx.config.typingContinueCommentsOnNewline) {
9075
ctx.pushExtCleanup(configureLanguage());
9176
}
9277

9378
vscode.workspace.onDidChangeConfiguration(
94-
(_) =>
95-
ctx
96-
.getClient()
97-
.then((it) =>
98-
it.sendNotification("workspace/didChangeConfiguration", { settings: "" })
99-
)
100-
.catch(log.error),
79+
async (_) => {
80+
await ctx
81+
.clientFetcher()
82+
.client?.sendNotification("workspace/didChangeConfiguration", { settings: "" });
83+
},
10184
null,
10285
ctx.subscriptions
10386
);
10487

88+
await ctx.activate().catch((err) => {
89+
void vscode.window.showErrorMessage(`Cannot activate rust-analyzer server: ${err.message}`);
90+
});
91+
10592
return ctx.clientFetcher();
10693
}
10794

@@ -130,6 +117,7 @@ async function initCommonContext(ctx: Ctx) {
130117
// Commands which invokes manually via command palette, shortcut, etc.
131118
ctx.registerCommand("reload", (_) => async () => {
132119
void vscode.window.showInformationMessage("Reloading rust-analyzer...");
120+
// FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed
133121
await ctx.disposeClient();
134122
await ctx.activate();
135123
});

0 commit comments

Comments
 (0)