mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 05:53:45 +00:00
Properly reload changed configs for server start
This commit is contained in:
parent
6f435977df
commit
8aaafddee8
4 changed files with 51 additions and 57 deletions
|
@ -310,6 +310,10 @@ export function ssr(ctx: Ctx): Cmd {
|
||||||
|
|
||||||
export function serverVersion(ctx: Ctx): Cmd {
|
export function serverVersion(ctx: Ctx): Cmd {
|
||||||
return async () => {
|
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 { stdout } = spawnSync(ctx.serverPath, ["--version"], { encoding: "utf8" });
|
||||||
const versionString = stdout.slice(`rust-analyzer `.length).trim();
|
const versionString = stdout.slice(`rust-analyzer `.length).trim();
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,6 @@ export class Config {
|
||||||
|
|
||||||
readonly rootSection = "rust-analyzer";
|
readonly rootSection = "rust-analyzer";
|
||||||
private readonly requiresWorkspaceReloadOpts = [
|
private readonly requiresWorkspaceReloadOpts = [
|
||||||
"serverPath",
|
|
||||||
"server",
|
|
||||||
// FIXME: This shouldn't be here, changing this setting should reload
|
// FIXME: This shouldn't be here, changing this setting should reload
|
||||||
// `continueCommentsOnNewline` behavior without restart
|
// `continueCommentsOnNewline` behavior without restart
|
||||||
"typing",
|
"typing",
|
||||||
|
@ -23,6 +21,8 @@ export class Config {
|
||||||
private readonly requiresReloadOpts = [
|
private readonly requiresReloadOpts = [
|
||||||
"cargo",
|
"cargo",
|
||||||
"procMacro",
|
"procMacro",
|
||||||
|
"serverPath",
|
||||||
|
"server",
|
||||||
"files",
|
"files",
|
||||||
"lens", // works as lens.*
|
"lens", // works as lens.*
|
||||||
]
|
]
|
||||||
|
|
|
@ -6,6 +6,8 @@ import { Config, substituteVariablesInEnv, substituteVSCodeVariables } from "./c
|
||||||
import { createClient } from "./client";
|
import { createClient } from "./client";
|
||||||
import { isRustEditor, log, RustEditor } from "./util";
|
import { isRustEditor, log, RustEditor } from "./util";
|
||||||
import { ServerStatusParams } from "./lsp_ext";
|
import { ServerStatusParams } from "./lsp_ext";
|
||||||
|
import { PersistentState } from "./persistent_state";
|
||||||
|
import { bootstrap } from "./bootstrap";
|
||||||
|
|
||||||
export type Workspace =
|
export type Workspace =
|
||||||
| {
|
| {
|
||||||
|
@ -17,28 +19,18 @@ export type Workspace =
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Ctx {
|
export class Ctx {
|
||||||
private client: lc.LanguageClient | undefined;
|
|
||||||
readonly config: Config;
|
|
||||||
serverPath: string;
|
|
||||||
readonly statusBar: vscode.StatusBarItem;
|
readonly statusBar: vscode.StatusBarItem;
|
||||||
|
readonly config: Config;
|
||||||
|
|
||||||
|
private client: lc.LanguageClient | undefined;
|
||||||
|
|
||||||
traceOutputChannel: vscode.OutputChannel | undefined;
|
traceOutputChannel: vscode.OutputChannel | undefined;
|
||||||
outputChannel: vscode.OutputChannel | undefined;
|
outputChannel: vscode.OutputChannel | undefined;
|
||||||
|
|
||||||
serverOptions:
|
|
||||||
| {
|
|
||||||
run: lc.Executable;
|
|
||||||
debug: lc.Executable;
|
|
||||||
}
|
|
||||||
| undefined;
|
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
|
state: PersistentState;
|
||||||
|
serverPath: string | undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(readonly extCtx: vscode.ExtensionContext, workspace: Workspace) {
|
||||||
readonly extCtx: vscode.ExtensionContext,
|
|
||||||
config: Config,
|
|
||||||
serverPath: string,
|
|
||||||
workspace: Workspace
|
|
||||||
) {
|
|
||||||
this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
|
this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
|
||||||
extCtx.subscriptions.push(this.statusBar);
|
extCtx.subscriptions.push(this.statusBar);
|
||||||
extCtx.subscriptions.push({
|
extCtx.subscriptions.push({
|
||||||
|
@ -50,9 +42,10 @@ export class Ctx {
|
||||||
this.statusBar.tooltip = "ready";
|
this.statusBar.tooltip = "ready";
|
||||||
this.statusBar.command = "rust-analyzer.analyzerStatus";
|
this.statusBar.command = "rust-analyzer.analyzerStatus";
|
||||||
this.statusBar.show();
|
this.statusBar.show();
|
||||||
this.serverPath = serverPath;
|
|
||||||
this.config = config;
|
|
||||||
this.workspace = workspace;
|
this.workspace = workspace;
|
||||||
|
|
||||||
|
this.state = new PersistentState(extCtx.globalState);
|
||||||
|
this.config = new Config(extCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
clientFetcher() {
|
clientFetcher() {
|
||||||
|
@ -64,6 +57,7 @@ export class Ctx {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getClient() {
|
async getClient() {
|
||||||
|
// if server path changes -> dispose
|
||||||
if (!this.traceOutputChannel) {
|
if (!this.traceOutputChannel) {
|
||||||
this.traceOutputChannel = vscode.window.createOutputChannel(
|
this.traceOutputChannel = vscode.window.createOutputChannel(
|
||||||
"Rust Analyzer Language Server Trace"
|
"Rust Analyzer Language Server Trace"
|
||||||
|
@ -72,8 +66,20 @@ export class Ctx {
|
||||||
if (!this.outputChannel) {
|
if (!this.outputChannel) {
|
||||||
this.outputChannel = vscode.window.createOutputChannel("Rust Analyzer Language Server");
|
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(
|
const newEnv = substituteVariablesInEnv(
|
||||||
Object.assign({}, process.env, this.config.serverExtraEnv)
|
Object.assign({}, process.env, this.config.serverExtraEnv)
|
||||||
);
|
);
|
||||||
|
@ -81,16 +87,11 @@ export class Ctx {
|
||||||
command: this.serverPath,
|
command: this.serverPath,
|
||||||
options: { env: newEnv },
|
options: { env: newEnv },
|
||||||
};
|
};
|
||||||
this.serverOptions = {
|
const serverOptions = {
|
||||||
run,
|
run,
|
||||||
debug: 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");
|
let rawInitializationOptions = vscode.workspace.getConfiguration("rust-analyzer");
|
||||||
|
|
||||||
if (this.workspace.kind === "Detached Files") {
|
if (this.workspace.kind === "Detached Files") {
|
||||||
|
@ -106,7 +107,7 @@ export class Ctx {
|
||||||
this.traceOutputChannel,
|
this.traceOutputChannel,
|
||||||
this.outputChannel,
|
this.outputChannel,
|
||||||
initializationOptions,
|
initializationOptions,
|
||||||
this.serverOptions
|
serverOptions
|
||||||
);
|
);
|
||||||
this.client.onNotification(ra.serverStatus, (params) => this.setServerStatus(params));
|
this.client.onNotification(ra.serverStatus, (params) => this.setServerStatus(params));
|
||||||
}
|
}
|
||||||
|
@ -128,6 +129,7 @@ export class Ctx {
|
||||||
async disposeClient() {
|
async disposeClient() {
|
||||||
log.info("Deactivating language client");
|
log.info("Deactivating language client");
|
||||||
await this.client?.dispose();
|
await this.client?.dispose();
|
||||||
|
this.serverPath = undefined;
|
||||||
this.client = undefined;
|
this.client = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,9 @@ import * as lc from "vscode-languageclient/node";
|
||||||
|
|
||||||
import * as commands from "./commands";
|
import * as commands from "./commands";
|
||||||
import { Ctx, Workspace } from "./ctx";
|
import { Ctx, Workspace } from "./ctx";
|
||||||
import { log, isRustDocument } from "./util";
|
import { isRustDocument } from "./util";
|
||||||
import { PersistentState } from "./persistent_state";
|
|
||||||
import { activateTaskProvider } from "./tasks";
|
import { activateTaskProvider } from "./tasks";
|
||||||
import { setContextValue } from "./util";
|
import { setContextValue } from "./util";
|
||||||
import { bootstrap } from "./bootstrap";
|
|
||||||
import { Config } from "./config";
|
|
||||||
|
|
||||||
const RUST_PROJECT_CONTEXT_NAME = "inRustProject";
|
const RUST_PROJECT_CONTEXT_NAME = "inRustProject";
|
||||||
|
|
||||||
|
@ -56,24 +53,13 @@ export async function activate(
|
||||||
}
|
}
|
||||||
: { kind: "Workspace Folder" };
|
: { kind: "Workspace Folder" };
|
||||||
|
|
||||||
const state = new PersistentState(context.globalState);
|
const ctx = new Ctx(context, workspace);
|
||||||
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);
|
|
||||||
// VS Code doesn't show a notification when an extension fails to activate
|
// VS Code doesn't show a notification when an extension fails to activate
|
||||||
// so we do it ourselves.
|
// so we do it ourselves.
|
||||||
return await activateServer(ctx).catch((err) => {
|
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;
|
throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -83,7 +69,6 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
|
||||||
ctx.pushExtCleanup(activateTaskProvider(ctx.config));
|
ctx.pushExtCleanup(activateTaskProvider(ctx.config));
|
||||||
}
|
}
|
||||||
|
|
||||||
await ctx.activate();
|
|
||||||
await initCommonContext(ctx);
|
await initCommonContext(ctx);
|
||||||
|
|
||||||
if (ctx.config.typingContinueCommentsOnNewline) {
|
if (ctx.config.typingContinueCommentsOnNewline) {
|
||||||
|
@ -91,17 +76,19 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
|
||||||
}
|
}
|
||||||
|
|
||||||
vscode.workspace.onDidChangeConfiguration(
|
vscode.workspace.onDidChangeConfiguration(
|
||||||
(_) =>
|
async (_) => {
|
||||||
ctx
|
await ctx
|
||||||
.getClient()
|
.clientFetcher()
|
||||||
.then((it) =>
|
.client?.sendNotification("workspace/didChangeConfiguration", { settings: "" });
|
||||||
it.sendNotification("workspace/didChangeConfiguration", { settings: "" })
|
},
|
||||||
)
|
|
||||||
.catch(log.error),
|
|
||||||
null,
|
null,
|
||||||
ctx.subscriptions
|
ctx.subscriptions
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await ctx.activate().catch((err) => {
|
||||||
|
void vscode.window.showErrorMessage(`Cannot activate rust-analyzer server: ${err.message}`);
|
||||||
|
});
|
||||||
|
|
||||||
return ctx.clientFetcher();
|
return ctx.clientFetcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +117,7 @@ async function initCommonContext(ctx: Ctx) {
|
||||||
// Commands which invokes manually via command palette, shortcut, etc.
|
// Commands which invokes manually via command palette, shortcut, etc.
|
||||||
ctx.registerCommand("reload", (_) => async () => {
|
ctx.registerCommand("reload", (_) => async () => {
|
||||||
void vscode.window.showInformationMessage("Reloading rust-analyzer...");
|
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.disposeClient();
|
||||||
await ctx.activate();
|
await ctx.activate();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue