mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 05:08:52 +00:00
feat: support UpdateTest in codelens
This commit is contained in:
parent
dd788255b4
commit
edb61b10ab
12 changed files with 204 additions and 57 deletions
|
@ -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,
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
|
|
|
@ -3213,6 +3213,11 @@ fn foo_$0test() {}
|
|||
},
|
||||
},
|
||||
cfg: None,
|
||||
update_test: UpdateTest {
|
||||
expect_test: false,
|
||||
insta: false,
|
||||
snapbox: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
]
|
||||
|
@ -3248,6 +3253,11 @@ mod tests$0 {
|
|||
path: "tests",
|
||||
},
|
||||
cfg: None,
|
||||
update_test: UpdateTest {
|
||||
expect_test: false,
|
||||
insta: false,
|
||||
snapbox: false,
|
||||
},
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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: `[]`)::
|
||||
+
|
||||
--
|
||||
|
|
|
@ -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."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2295,6 +2300,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": {
|
||||
|
|
|
@ -398,8 +398,7 @@ 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
|
||||
return `[${cmd.title}](command:rust-analyzer.hoverRefCommandProxy?${HOVER_REFERENCE_COMMAND.length - 1
|
||||
} '${cmd.tooltip}')`;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue