diff options
| author | roife <roifewu@gmail.com> | 2024-12-25 15:56:06 +0800 |
|---|---|---|
| committer | roife <roifewu@gmail.com> | 2024-12-26 19:50:32 +0800 |
| commit | 60b4ed5bd36e88b454c8833f76a7481e01cca66a (patch) | |
| tree | 1cfbd1609908ce2780ce0ed6ca827bc836c14d30 | |
| parent | 08677cb70dce85e1ad4f0e5a5e3dfecf77ec16fd (diff) | |
| download | rust-60b4ed5bd36e88b454c8833f76a7481e01cca66a.tar.gz rust-60b4ed5bd36e88b454c8833f76a7481e01cca66a.zip | |
feat: support UpdateTest in codelens
12 files changed, 204 insertions, 57 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs index 121a463c9f1..6a4e5ba290e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs +++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs @@ -316,6 +316,11 @@ fn main() { }, kind: Bin, cfg: None, + update_test: UpdateTest { + expect_test: false, + insta: false, + snapbox: false, + }, }, ), }, @@ -401,6 +406,11 @@ fn main() { }, kind: Bin, cfg: None, + update_test: UpdateTest { + expect_test: false, + insta: false, + snapbox: false, + }, }, ), }, @@ -537,6 +547,11 @@ fn main() { }, kind: Bin, cfg: None, + update_test: UpdateTest { + expect_test: false, + insta: false, + snapbox: false, + }, }, ), }, @@ -597,6 +612,11 @@ fn main() {} }, kind: Bin, cfg: None, + update_test: UpdateTest { + expect_test: false, + insta: false, + snapbox: false, + }, }, ), }, @@ -709,6 +729,11 @@ fn main() { }, kind: Bin, cfg: None, + update_test: UpdateTest { + expect_test: false, + insta: false, + snapbox: false, + }, }, ), }, @@ -746,6 +771,20 @@ mod tests { [ Annotation { range: 3..7, + kind: HasReferences { + pos: FilePositionWrapper { + file_id: FileId( + 0, + ), + offset: 3, + }, + data: Some( + [], + ), + }, + }, + Annotation { + range: 3..7, kind: Runnable( Runnable { use_name_in_title: false, @@ -760,24 +799,15 @@ mod tests { }, kind: Bin, cfg: None, + update_test: UpdateTest { + expect_test: false, + insta: false, + snapbox: false, + }, }, ), }, Annotation { - range: 3..7, - kind: HasReferences { - pos: FilePositionWrapper { - file_id: FileId( - 0, - ), - offset: 3, - }, - data: Some( - [], - ), - }, - }, - Annotation { range: 18..23, kind: Runnable( Runnable { @@ -796,6 +826,11 @@ mod tests { path: "tests", }, cfg: None, + update_test: UpdateTest { + expect_test: false, + insta: false, + snapbox: false, + }, }, ), }, @@ -822,6 +857,11 @@ mod tests { }, }, cfg: None, + update_test: UpdateTest { + expect_test: false, + insta: false, + snapbox: false, + }, }, ), }, diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index ed8cd64cdbe..a7a5b8fb5a1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -3213,6 +3213,11 @@ fn foo_$0test() {} }, }, cfg: None, + update_test: UpdateTest { + expect_test: false, + insta: false, + snapbox: false, + }, }, ), ] @@ -3230,28 +3235,33 @@ mod tests$0 { } "#, expect![[r#" - [ - Runnable( - Runnable { - use_name_in_title: false, - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..46, - focus_range: 4..9, - name: "tests", - kind: Module, - description: "mod tests", - }, - kind: TestMod { - path: "tests", - }, - cfg: None, + [ + Runnable( + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..46, + focus_range: 4..9, + name: "tests", + kind: Module, + description: "mod tests", }, - ), - ] - "#]], + kind: TestMod { + path: "tests", + }, + cfg: None, + update_test: UpdateTest { + expect_test: false, + insta: false, + snapbox: false, + }, + }, + ), + ] + "#]], ); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index c182952c731..1b37ab0aab2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -243,6 +243,9 @@ config_data! { /// Whether to show `Run` lens. Only applies when /// `#rust-analyzer.lens.enable#` is set. lens_run_enable: bool = true, + /// Whether to show `Update Test` lens. Only applies when + /// `#rust-analyzer.lens.enable#` and `#rust-analyzer.lens.run.enable#` are set. + lens_update_test_enable: bool = true, /// Disable project auto-discovery in favor of explicitly specified set /// of projects. @@ -1161,6 +1164,7 @@ pub struct LensConfig { // runnables pub run: bool, pub debug: bool, + pub update_test: bool, pub interpret: bool, // implementations @@ -1196,6 +1200,7 @@ impl LensConfig { pub fn any(&self) -> bool { self.run || self.debug + || self.update_test || self.implementations || self.method_refs || self.refs_adt @@ -1208,7 +1213,7 @@ impl LensConfig { } pub fn runnable(&self) -> bool { - self.run || self.debug + self.run || self.debug || self.update_test } pub fn references(&self) -> bool { @@ -2120,6 +2125,9 @@ impl Config { LensConfig { run: *self.lens_enable() && *self.lens_run_enable(), debug: *self.lens_enable() && *self.lens_debug_enable(), + update_test: *self.lens_enable() + && *self.lens_update_test_enable() + && *self.lens_run_enable(), interpret: *self.lens_enable() && *self.lens_run_enable() && *self.interpret_tests(), implementations: *self.lens_enable() && *self.lens_implementations_enable(), method_refs: *self.lens_enable() && *self.lens_references_method_enable(), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs index c0173d9c247..e1677cbcda8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs @@ -427,14 +427,14 @@ impl Request for Runnables { const METHOD: &'static str = "experimental/runnables"; } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase")] pub struct RunnablesParams { pub text_document: TextDocumentIdentifier, pub position: Option<Position>, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, Clone)] #[serde(rename_all = "camelCase")] pub struct Runnable { pub label: String, @@ -444,7 +444,7 @@ pub struct Runnable { pub args: RunnableArgs, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, Clone)] #[serde(rename_all = "camelCase")] #[serde(untagged)] pub enum RunnableArgs { @@ -452,14 +452,14 @@ pub enum RunnableArgs { Shell(ShellRunnableArgs), } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "lowercase")] pub enum RunnableKind { Cargo, Shell, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, Clone)] #[serde(rename_all = "camelCase")] pub struct CargoRunnableArgs { #[serde(skip_serializing_if = "FxHashMap::is_empty")] @@ -475,7 +475,7 @@ pub struct CargoRunnableArgs { pub executable_args: Vec<String>, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, Clone)] #[serde(rename_all = "camelCase")] pub struct ShellRunnableArgs { #[serde(skip_serializing_if = "FxHashMap::is_empty")] diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index 05e93b4e6ac..091ac773323 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -20,6 +20,7 @@ use itertools::Itertools; use paths::{Utf8Component, Utf8Prefix}; use semver::VersionReq; use serde_json::to_value; +use syntax::SmolStr; use vfs::AbsPath; use crate::{ @@ -1567,6 +1568,7 @@ pub(crate) fn code_lens( let line_index = snap.file_line_index(run.nav.file_id)?; let annotation_range = range(&line_index, annotation.range); + let update_test = run.update_test; let title = run.title(); let can_debug = match run.kind { ide::RunnableKind::DocTest { .. } => false, @@ -1602,6 +1604,17 @@ pub(crate) fn code_lens( data: None, }) } + if lens_config.update_test && client_commands_config.run_single { + let label = update_test.label(); + if let Some(r) = make_update_runnable(&r, &label) { + let command = command::run_single(&r, label.unwrap().as_str()); + acc.push(lsp_types::CodeLens { + range: annotation_range, + command: Some(command), + data: None, + }) + } + } } if lens_config.interpret { @@ -1786,7 +1799,7 @@ pub(crate) mod command { pub(crate) fn debug_single(runnable: &lsp_ext::Runnable) -> lsp_types::Command { lsp_types::Command { - title: "Debug".into(), + title: "⚙\u{fe0e} Debug".into(), command: "rust-analyzer.debugSingle".into(), arguments: Some(vec![to_value(runnable).unwrap()]), } @@ -1838,6 +1851,29 @@ pub(crate) mod command { } } +fn make_update_runnable( + runnable: &lsp_ext::Runnable, + label: &Option<SmolStr>, +) -> Option<lsp_ext::Runnable> { + if !matches!(runnable.args, lsp_ext::RunnableArgs::Cargo(_)) { + return None; + } + let label = label.as_ref()?; + + let mut runnable = runnable.clone(); + runnable.label = format!("{} + {}", runnable.label, label); + + let lsp_ext::RunnableArgs::Cargo(r) = &mut runnable.args else { + unreachable!(); + }; + + let environment_vars = + [("UPDATE_EXPECT", "1"), ("INSTA_UPDATE", "always"), ("SNAPSHOTS", "overwrite")]; + r.environment.extend(environment_vars.into_iter().map(|(k, v)| (k.to_owned(), v.to_owned()))); + + Some(runnable) +} + pub(crate) fn implementation_title(count: usize) -> String { if count == 1 { "1 implementation".into() diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md index 0e37611a549..826ce112448 100644 --- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@ <!--- -lsp/ext.rs hash: 9790509d87670c22 +lsp/ext.rs hash: 512c06cd8b46a21d If you need to change the above hash to make the test pass, please check if you need to adjust this doc as well and ping this issue: diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index 5056c7d977c..f5cdcc2b726 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -808,6 +808,12 @@ Only applies when `#rust-analyzer.lens.enable#` is set. Whether to show `Run` lens. Only applies when `#rust-analyzer.lens.enable#` is set. -- +[[rust-analyzer.lens.update.test.enable]]rust-analyzer.lens.update.test.enable (default: `true`):: ++ +-- +Whether to show `Update Test` lens. Only applies when +`#rust-analyzer.lens.enable#` and `#rust-analyzer.lens.run.enable#` are set. +-- [[rust-analyzer.linkedProjects]]rust-analyzer.linkedProjects (default: `[]`):: + -- diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index b9249e9ac8b..7dc26c44366 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -407,6 +407,11 @@ "$rustc" ], "markdownDescription": "Problem matchers to use for `rust-analyzer.run` command, eg `[\"$rustc\", \"$rust-panic\"]`." + }, + "rust-analyzer.runnables.askBeforeUpdateTest": { + "type": "boolean", + "default": true, + "markdownDescription": "Ask before updating the test when running it." } } }, @@ -2296,6 +2301,16 @@ } }, { + "title": "lens", + "properties": { + "rust-analyzer.lens.update.test.enable": { + "markdownDescription": "Whether to show `Update Test` lens. Only applies when\n`#rust-analyzer.lens.enable#` and `#rust-analyzer.lens.run.enable#` are set.", + "default": true, + "type": "boolean" + } + } + }, + { "title": "general", "properties": { "rust-analyzer.linkedProjects": { diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts index eac7b849fdb..5d33d7a6adb 100644 --- a/src/tools/rust-analyzer/editors/code/src/client.ts +++ b/src/tools/rust-analyzer/editors/code/src/client.ts @@ -348,9 +348,9 @@ class ExperimentalFeatures implements lc.StaticFeature { initialize( _capabilities: lc.ServerCapabilities, _documentSelector: lc.DocumentSelector | undefined, - ): void {} - dispose(): void {} - clear(): void {} + ): void { } + dispose(): void { } + clear(): void { } } class OverrideFeatures implements lc.StaticFeature { @@ -368,9 +368,9 @@ class OverrideFeatures implements lc.StaticFeature { initialize( _capabilities: lc.ServerCapabilities, _documentSelector: lc.DocumentSelector | undefined, - ): void {} - dispose(): void {} - clear(): void {} + ): void { } + dispose(): void { } + clear(): void { } } function isCodeActionWithoutEditsAndCommands(value: any): boolean { @@ -398,9 +398,8 @@ export let HOVER_REFERENCE_COMMAND: ra.CommandLink[] = []; function renderCommand(cmd: ra.CommandLink): string { HOVER_REFERENCE_COMMAND.push(cmd); - return `[${cmd.title}](command:rust-analyzer.hoverRefCommandProxy?${ - HOVER_REFERENCE_COMMAND.length - 1 - } '${cmd.tooltip}')`; + return `[${cmd.title}](command:rust-analyzer.hoverRefCommandProxy?${HOVER_REFERENCE_COMMAND.length - 1 + } '${cmd.tooltip}')`; } function renderHoverActions(actions: ra.CommandLinkGroup[]): vscode.MarkdownString { diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts index 7ebc186a3ea..dc35fddf49e 100644 --- a/src/tools/rust-analyzer/editors/code/src/commands.ts +++ b/src/tools/rust-analyzer/editors/code/src/commands.ts @@ -1139,11 +1139,37 @@ export function peekTests(ctx: CtxInit): Cmd { }; } +function isUpdatingTest(runnable: ra.Runnable): boolean { + if (!isCargoRunnableArgs(runnable.args)) { + return false; + } + + const env = runnable.args.environment; + return env ? ['UPDATE_EXPECT', 'INSTA_UPDATE', 'SNAPSHOTS'].some(key => key in env) : false; +} + export function runSingle(ctx: CtxInit): Cmd { return async (runnable: ra.Runnable) => { const editor = ctx.activeRustEditor; if (!editor) return; + if (isUpdatingTest(runnable) && ctx.config.askBeforeUpdateTest) { + const selection = await vscode.window.showInformationMessage( + 'rust-analyzer', + { detail: 'Do you want to update tests?', modal: true }, + 'Update Now', + 'Update (and Don\'t ask again)', + ); + + if (selection !== 'Update Now' && selection !== 'Update (and Don\'t ask again)') { + return; + } + + if (selection === 'Update (and Don\'t ask again)') { + ctx.config.setAskBeforeUpdateTest(false); + } + } + const task = await createTaskFromRunnable(runnable, ctx.config); task.group = vscode.TaskGroup.Build; task.presentationOptions = { diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts index a97d4beab51..720c473c5b4 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -362,6 +362,13 @@ export class Config { get initializeStopped() { return this.get<boolean>("initializeStopped"); } + + get askBeforeUpdateTest() { + return this.get<boolean>("runnables.askBeforeUpdateTest"); + } + async setAskBeforeUpdateTest(value: boolean) { + await this.cfg.update("runnables.askBeforeUpdateTest", value, true); + } } export function prepareVSCodeConfig<T>(resp: T): T { diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts index fdf43f66f94..478673d5915 100644 --- a/src/tools/rust-analyzer/editors/code/src/main.ts +++ b/src/tools/rust-analyzer/editors/code/src/main.ts @@ -148,7 +148,7 @@ function createCommands(): Record<string, CommandFactory> { health: "stopped", }); }, - disabled: (_) => async () => {}, + disabled: (_) => async () => { }, }, analyzerStatus: { enabled: commands.analyzerStatus }, @@ -207,10 +207,10 @@ function checkConflictingExtensions() { vscode.window .showWarningMessage( `You have both the rust-analyzer (rust-lang.rust-analyzer) and Rust (rust-lang.rust) ` + - "plugins enabled. These are known to conflict and cause various functions of " + - "both plugins to not work correctly. You should disable one of them.", + "plugins enabled. These are known to conflict and cause various functions of " + + "both plugins to not work correctly. You should disable one of them.", "Got it", ) - .then(() => {}, console.error); + .then(() => { }, console.error); } } |
