⬆️ rust-analyzer

This commit is contained in:
Laurențiu Nicola 2022-11-23 17:24:03 +02:00
parent 61c744d4fd
commit a2a1d99545
126 changed files with 2098 additions and 904 deletions

View file

@ -396,6 +396,11 @@
"default": true,
"type": "boolean"
},
"rust-analyzer.diagnostics.previewRustcOutput": {
"markdownDescription": "Whether to show the main part of the rendered rustc output of a diagnostic message.",
"default": false,
"type": "boolean"
},
"$generated-start": {},
"rust-analyzer.assist.emitMustUse": {
"markdownDescription": "Whether to insert #[must_use] when generating `as_` methods\nfor enum variants.",
@ -623,7 +628,7 @@
]
},
"rust-analyzer.checkOnSave.overrideCommand": {
"markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefor include `--message-format=json` or a similar option.\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects, this command is invoked for\neach of them, with the working directory being the project root\n(i.e., the folder containing the `Cargo.toml`).\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.",
"markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefore include `--message-format=json` or a similar option.\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects, this command is invoked for\neach of them, with the working directory being the project root\n(i.e., the folder containing the `Cargo.toml`).\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.",
"default": null,
"type": [
"null",
@ -634,11 +639,18 @@
}
},
"rust-analyzer.checkOnSave.target": {
"markdownDescription": "Check for a specific target. Defaults to\n`#rust-analyzer.cargo.target#`.",
"default": null,
"type": [
"null",
"string"
"markdownDescription": "Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.\n\nCan be a single target, e.g. `\"x86_64-unknown-linux-gnu\"` or a list of targets, e.g.\n`[\"aarch64-apple-darwin\", \"x86_64-apple-darwin\"]`.\n\nAliased as `\"checkOnSave.targets\"`.",
"default": [],
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
},
"rust-analyzer.completion.autoimport.enable": {
@ -935,6 +947,21 @@
"Only show type hints for return types of closures with blocks."
]
},
"rust-analyzer.inlayHints.expressionAdjustmentHints.enable": {
"markdownDescription": "Whether to show inlay hints for type adjustments.",
"default": "never",
"type": "string",
"enum": [
"always",
"never",
"reborrow"
],
"enumDescriptions": [
"Always show all adjustment hints.",
"Never show adjustment hints.",
"Only show auto borrow and dereference adjustment hints."
]
},
"rust-analyzer.inlayHints.lifetimeElisionHints.enable": {
"markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.",
"default": "never",
@ -970,7 +997,7 @@
"type": "boolean"
},
"rust-analyzer.inlayHints.reborrowHints.enable": {
"markdownDescription": "Whether to show inlay type hints for compiler inserted reborrows.",
"markdownDescription": "Whether to show inlay hints for compiler inserted reborrows.\nThis setting is deprecated in favor of #rust-analyzer.inlayHints.expressionAdjustmentHints.enable#.",
"default": "never",
"type": "string",
"enum": [
@ -1276,6 +1303,11 @@
"$generated-end": {}
}
},
"configurationDefaults": {
"explorer.fileNesting.patterns": {
"Cargo.toml": "Cargo.lock"
}
},
"problemPatterns": [
{
"name": "rustc",

View file

@ -4,7 +4,7 @@ import * as ra from "../src/lsp_ext";
import * as Is from "vscode-languageclient/lib/common/utils/is";
import { assert } from "./util";
import { WorkspaceEdit } from "vscode";
import { substituteVSCodeVariables } from "./config";
import { Config, substituteVSCodeVariables } from "./config";
import { randomUUID } from "crypto";
export interface Env {
@ -66,7 +66,8 @@ export async function createClient(
traceOutputChannel: vscode.OutputChannel,
outputChannel: vscode.OutputChannel,
initializationOptions: vscode.WorkspaceConfiguration,
serverOptions: lc.ServerOptions
serverOptions: lc.ServerOptions,
config: Config
): Promise<lc.LanguageClient> {
const clientOptions: lc.LanguageClientOptions = {
documentSelector: [{ scheme: "file", language: "rust" }],
@ -99,6 +100,43 @@ export async function createClient(
}
},
},
async handleDiagnostics(
uri: vscode.Uri,
diagnostics: vscode.Diagnostic[],
next: lc.HandleDiagnosticsSignature
) {
const preview = config.previewRustcOutput;
diagnostics.forEach((diag, idx) => {
// Abuse the fact that VSCode leaks the LSP diagnostics data field through the
// Diagnostic class, if they ever break this we are out of luck and have to go
// back to the worst diagnostics experience ever:)
// We encode the rendered output of a rustc diagnostic in the rendered field of
// the data payload of the lsp diagnostic. If that field exists, overwrite the
// diagnostic code such that clicking it opens the diagnostic in a readonly
// text editor for easy inspection
const rendered = (diag as unknown as { data?: { rendered?: string } }).data
?.rendered;
if (rendered) {
if (preview) {
const index = rendered.match(/^(note|help):/m)?.index || 0;
diag.message = rendered
.substring(0, index)
.replace(/^ -->[^\n]+\n/m, "");
}
diag.code = {
target: vscode.Uri.from({
scheme: "rust-analyzer-diagnostics-view",
path: "/diagnostic message",
fragment: uri.toString(),
query: idx.toString(),
}),
value: "Click for full compiler diagnostic",
};
}
});
return next(uri, diagnostics);
},
async provideHover(
document: vscode.TextDocument,
position: vscode.Position,

View file

@ -238,6 +238,9 @@ export class Config {
gotoTypeDef: this.get<boolean>("hover.actions.gotoTypeDef.enable"),
};
}
get previewRustcOutput() {
return this.get<boolean>("diagnostics.previewRustcOutput");
}
}
const VarRegex = new RegExp(/\$\{(.+?)\}/g);

View file

@ -179,7 +179,8 @@ export class Ctx {
this.traceOutputChannel,
this.outputChannel,
initializationOptions,
serverOptions
serverOptions,
this.config
);
this.pushClientCleanup(
this._client.onNotification(ra.serverStatus, (params) =>

View file

@ -48,6 +48,30 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
ctx.pushExtCleanup(activateTaskProvider(ctx.config));
}
ctx.pushExtCleanup(
vscode.workspace.registerTextDocumentContentProvider(
"rust-analyzer-diagnostics-view",
new (class implements vscode.TextDocumentContentProvider {
async provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
const diags = ctx.client?.diagnostics?.get(
vscode.Uri.parse(uri.fragment, true)
);
if (!diags) {
return "Unable to find original rustc diagnostic";
}
const diag = diags[parseInt(uri.query)];
if (!diag) {
return "Unable to find original rustc diagnostic";
}
const rendered = (diag as unknown as { data?: { rendered?: string } }).data
?.rendered;
return rendered ?? "Unable to find original rustc diagnostic";
}
})()
)
);
vscode.workspace.onDidChangeWorkspaceFolders(
async (_) => ctx.onWorkspaceFolderChanges(),
null,