mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 05:53:45 +00:00
internal: Properly handle language configuration config changes
This commit is contained in:
parent
f3cce5feea
commit
a8e0a20ce4
3 changed files with 88 additions and 80 deletions
|
@ -11,13 +11,9 @@ export type RunnableEnvCfg =
|
||||||
|
|
||||||
export class Config {
|
export class Config {
|
||||||
readonly extensionId = "rust-lang.rust-analyzer";
|
readonly extensionId = "rust-lang.rust-analyzer";
|
||||||
|
configureLang: vscode.Disposable | undefined;
|
||||||
|
|
||||||
readonly rootSection = "rust-analyzer";
|
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 = [
|
private readonly requiresReloadOpts = [
|
||||||
"cargo",
|
"cargo",
|
||||||
"procMacro",
|
"procMacro",
|
||||||
|
@ -25,9 +21,7 @@ export class Config {
|
||||||
"server",
|
"server",
|
||||||
"files",
|
"files",
|
||||||
"lens", // works as lens.*
|
"lens", // works as lens.*
|
||||||
]
|
].map((opt) => `${this.rootSection}.${opt}`);
|
||||||
.map((opt) => `${this.rootSection}.${opt}`)
|
|
||||||
.concat(this.requiresWorkspaceReloadOpts);
|
|
||||||
|
|
||||||
readonly package: {
|
readonly package: {
|
||||||
version: string;
|
version: string;
|
||||||
|
@ -45,6 +39,11 @@ export class Config {
|
||||||
ctx.subscriptions
|
ctx.subscriptions
|
||||||
);
|
);
|
||||||
this.refreshLogging();
|
this.refreshLogging();
|
||||||
|
this.configureLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.configureLang?.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private refreshLogging() {
|
private refreshLogging() {
|
||||||
|
@ -58,33 +57,86 @@ export class Config {
|
||||||
private async onDidChangeConfiguration(event: vscode.ConfigurationChangeEvent) {
|
private async onDidChangeConfiguration(event: vscode.ConfigurationChangeEvent) {
|
||||||
this.refreshLogging();
|
this.refreshLogging();
|
||||||
|
|
||||||
|
this.configureLanguage();
|
||||||
|
|
||||||
const requiresReloadOpt = this.requiresReloadOpts.find((opt) =>
|
const requiresReloadOpt = this.requiresReloadOpts.find((opt) =>
|
||||||
event.affectsConfiguration(opt)
|
event.affectsConfiguration(opt)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!requiresReloadOpt) return;
|
if (!requiresReloadOpt) return;
|
||||||
|
|
||||||
const requiresWorkspaceReloadOpt = this.requiresWorkspaceReloadOpts.find((opt) =>
|
if (this.restartServerOnConfigChange) {
|
||||||
event.affectsConfiguration(opt)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!requiresWorkspaceReloadOpt && this.restartServerOnConfigChange) {
|
|
||||||
await vscode.commands.executeCommand("rust-analyzer.reload");
|
await vscode.commands.executeCommand("rust-analyzer.reload");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = requiresWorkspaceReloadOpt
|
const message = `Changing "${requiresReloadOpt}" requires a server restart`;
|
||||||
? `Changing "${requiresWorkspaceReloadOpt}" requires a window reload`
|
const userResponse = await vscode.window.showInformationMessage(message, "Restart now");
|
||||||
: `Changing "${requiresReloadOpt}" requires a reload`;
|
|
||||||
const userResponse = await vscode.window.showInformationMessage(message, "Reload now");
|
|
||||||
|
|
||||||
if (userResponse === "Reload now") {
|
if (userResponse) {
|
||||||
const command = requiresWorkspaceReloadOpt
|
const command = "rust-analyzer.reload";
|
||||||
? "workbench.action.reloadWindow"
|
await vscode.commands.executeCommand(command);
|
||||||
: "rust-analyzer.reload";
|
}
|
||||||
if (userResponse === "Reload now") {
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ export class Ctx {
|
||||||
this.dispose();
|
this.dispose();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
extCtx.subscriptions.push(this);
|
||||||
this.statusBar.text = "rust-analyzer";
|
this.statusBar.text = "rust-analyzer";
|
||||||
this.statusBar.tooltip = "ready";
|
this.statusBar.tooltip = "ready";
|
||||||
this.statusBar.command = "rust-analyzer.analyzerStatus";
|
this.statusBar.command = "rust-analyzer.analyzerStatus";
|
||||||
|
@ -48,10 +49,15 @@ export class Ctx {
|
||||||
this.config = new Config(extCtx);
|
this.config = new Config(extCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.config.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
clientFetcher() {
|
clientFetcher() {
|
||||||
|
const self = this;
|
||||||
return {
|
return {
|
||||||
get client(): lc.LanguageClient | undefined {
|
get client(): lc.LanguageClient | undefined {
|
||||||
return this.client;
|
return self.client;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,10 +77,6 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
|
||||||
|
|
||||||
await initCommonContext(ctx);
|
await initCommonContext(ctx);
|
||||||
|
|
||||||
if (ctx.config.typingContinueCommentsOnNewline) {
|
|
||||||
ctx.pushExtCleanup(configureLanguage());
|
|
||||||
}
|
|
||||||
|
|
||||||
vscode.workspace.onDidChangeConfiguration(
|
vscode.workspace.onDidChangeConfiguration(
|
||||||
async (_) => {
|
async (_) => {
|
||||||
await ctx
|
await ctx
|
||||||
|
@ -129,6 +125,11 @@ async function initCommonContext(ctx: Ctx) {
|
||||||
ctx.registerCommand("stopServer", (_) => async () => {
|
ctx.registerCommand("stopServer", (_) => async () => {
|
||||||
// FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed
|
// FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed
|
||||||
await ctx.disposeClient();
|
await ctx.disposeClient();
|
||||||
|
ctx.setServerStatus({
|
||||||
|
health: "ok",
|
||||||
|
quiescent: true,
|
||||||
|
message: "server is not running",
|
||||||
|
});
|
||||||
});
|
});
|
||||||
ctx.registerCommand("analyzerStatus", commands.analyzerStatus);
|
ctx.registerCommand("analyzerStatus", commands.analyzerStatus);
|
||||||
ctx.registerCommand("memoryUsage", commands.memoryUsage);
|
ctx.registerCommand("memoryUsage", commands.memoryUsage);
|
||||||
|
@ -172,54 +173,3 @@ async function initCommonContext(ctx: Ctx) {
|
||||||
defaultOnEnter.dispose();
|
defaultOnEnter.dispose();
|
||||||
ctx.registerCommand("onEnter", commands.onEnter);
|
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 },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue