From edb61b10ab49359dfdd82aafeef6cb4c5c1531ae Mon Sep 17 00:00:00 2001 From: roife Date: Wed, 25 Dec 2024 15:56:06 +0800 Subject: [PATCH] feat: support UpdateTest in codelens --- crates/ide/src/annotations.rs | 68 +++++++++++++++++++----- crates/ide/src/hover/tests.rs | 52 ++++++++++-------- crates/rust-analyzer/src/config.rs | 10 +++- crates/rust-analyzer/src/lsp/ext.rs | 12 ++--- crates/rust-analyzer/src/lsp/to_proto.rs | 38 ++++++++++++- docs/dev/lsp-extensions.md | 2 +- docs/user/generated_config.adoc | 6 +++ editors/code/package.json | 15 ++++++ editors/code/src/client.ts | 17 +++--- editors/code/src/commands.ts | 26 +++++++++ editors/code/src/config.ts | 7 +++ editors/code/src/main.ts | 8 +-- 12 files changed, 204 insertions(+), 57 deletions(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index 121a463c9f..6a4e5ba290 100644 --- a/crates/ide/src/annotations.rs +++ b/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, + }, }, ), }, @@ -744,6 +769,20 @@ mod tests { "#, expect![[r#" [ + Annotation { + range: 3..7, + kind: HasReferences { + pos: FilePositionWrapper { + file_id: FileId( + 0, + ), + offset: 3, + }, + data: Some( + [], + ), + }, + }, Annotation { range: 3..7, kind: Runnable( @@ -760,23 +799,14 @@ 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( @@ -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/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index ed8cd64cdb..a7a5b8fb5a 100644 --- a/crates/ide/src/hover/tests.rs +++ b/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/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index c182952c73..1b37ab0aab 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/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/crates/rust-analyzer/src/lsp/ext.rs b/crates/rust-analyzer/src/lsp/ext.rs index c0173d9c24..e1677cbcda 100644 --- a/crates/rust-analyzer/src/lsp/ext.rs +++ b/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, } -#[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, } -#[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/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index 05e93b4e6a..091ac77332 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/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, +) -> Option { + 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/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 0e37611a54..826ce11244 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@