Skip to content

Commit

Permalink
Auto merge of rust-lang#13451 - Veykril:lang-config, r=Veykril
Browse files Browse the repository at this point in the history
internal: Properly handle language configuration config changes
  • Loading branch information
bors committed Oct 20, 2022
2 parents 2481721 + a8e0a20 commit 69f01fd
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 81 deletions.
102 changes: 77 additions & 25 deletions editors/code/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,17 @@ 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",
"serverPath",
"server",
"files",
"lens", // works as lens.*
]
.map((opt) => `${this.rootSection}.${opt}`)
.concat(this.requiresWorkspaceReloadOpts);
].map((opt) => `${this.rootSection}.${opt}`);

readonly package: {
version: string;
Expand All @@ -45,6 +39,11 @@ export class Config {
ctx.subscriptions
);
this.refreshLogging();
this.configureLanguage();
}

dispose() {
this.configureLang?.dispose();
}

private refreshLogging() {
Expand All @@ -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");

if (userResponse === "Reload now") {
const command = requiresWorkspaceReloadOpt
? "workbench.action.reloadWindow"
: "rust-analyzer.reload";
if (userResponse === "Reload now") {
await vscode.commands.executeCommand(command);
}
const message = `Changing "${requiresReloadOpt}" requires a server restart`;
const userResponse = await vscode.window.showInformationMessage(message, "Restart now");

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;
}
}

Expand Down
8 changes: 7 additions & 1 deletion editors/code/src/ctx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;
},
};
}
Expand Down
60 changes: 5 additions & 55 deletions editors/code/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,6 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {

await initCommonContext(ctx);

if (ctx.config.typingContinueCommentsOnNewline) {
ctx.pushExtCleanup(configureLanguage());
}

vscode.workspace.onDidChangeConfiguration(
async (_) => {
await ctx
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 },
},
],
});
}

0 comments on commit 69f01fd

Please sign in to comment.