9449: feat: Emit test names in `Run test` runnables if they come from a macro expansion r=matklad a=Veykril

Fixes #8964
Before:
![Code_D1Tu5Iuh5I](https://user-images.githubusercontent.com/3757771/124174685-f552b380-daac-11eb-9086-c97db014b77c.png)
After:
![image](https://user-images.githubusercontent.com/3757771/124174493-bb81ad00-daac-11eb-96c7-3de6545a62e1.png)

Basically when a macro emits more than one test we name the test functions/modules name in the runnable instead to not emit a bunch of equally named `Run Test` annotations which don't really tell much.

Note that the `Run fibonacci_test Tests` line is below the attributes due to the fact that the function name span is being reused for the generated module in rstest's expansion.

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-07-11 09:37:33 +00:00 committed by GitHub
commit 325140a165
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 363 additions and 136 deletions

View File

@ -1634,6 +1634,16 @@ impl HasVisibility for AssocItem {
}
}
impl From<AssocItem> for ModuleDef {
fn from(assoc: AssocItem) -> Self {
match assoc {
AssocItem::Function(it) => ModuleDef::Function(it),
AssocItem::Const(it) => ModuleDef::Const(it),
AssocItem::TypeAlias(it) => ModuleDef::TypeAlias(it),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum GenericDef {
Function(Function),

View File

@ -57,24 +57,22 @@ pub(crate) fn annotations(
continue;
}
let action = runnable.action();
let range = runnable.nav.focus_or_full_range();
// dbg_runnable should go after the run annotation, to prevent a clone we do it this way
let dbg_runnable = (runnable.debugee() && config.debug).then(|| Annotation {
range,
kind: AnnotationKind::Runnable { debug: true, runnable: runnable.clone() },
});
if config.run {
annotations.push(Annotation {
range,
// FIXME: This one allocates without reason if run is enabled, but debug is disabled
kind: AnnotationKind::Runnable { debug: false, runnable: runnable.clone() },
kind: AnnotationKind::Runnable { debug: false, runnable },
});
}
if action.debugee && config.debug {
annotations.push(Annotation {
range,
kind: AnnotationKind::Runnable { debug: true, runnable },
});
}
annotations.extend(dbg_runnable);
}
}
@ -228,6 +226,7 @@ fn main() {
kind: Runnable {
debug: false,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -247,6 +246,7 @@ fn main() {
kind: Runnable {
debug: true,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -332,6 +332,7 @@ fn main() {
kind: Runnable {
debug: false,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -351,6 +352,7 @@ fn main() {
kind: Runnable {
debug: true,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -440,6 +442,7 @@ fn main() {
kind: Runnable {
debug: false,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -459,6 +462,7 @@ fn main() {
kind: Runnable {
debug: true,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -601,6 +605,7 @@ fn main() {}
kind: Runnable {
debug: false,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -620,6 +625,7 @@ fn main() {}
kind: Runnable {
debug: true,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -674,6 +680,7 @@ fn main() {
kind: Runnable {
debug: false,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -693,6 +700,7 @@ fn main() {
kind: Runnable {
debug: true,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -816,6 +824,7 @@ mod tests {
kind: Runnable {
debug: false,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -835,6 +844,7 @@ mod tests {
kind: Runnable {
debug: true,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -854,6 +864,7 @@ mod tests {
kind: Runnable {
debug: false,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -876,6 +887,7 @@ mod tests {
kind: Runnable {
debug: true,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -898,6 +910,7 @@ mod tests {
kind: Runnable {
debug: false,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -924,6 +937,7 @@ mod tests {
kind: Runnable {
debug: true,
runnable: Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,

View File

@ -2463,6 +2463,7 @@ fn foo_$0test() {}
),
Runnable(
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -2501,6 +2502,7 @@ mod tests$0 {
[
Runnable(
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,

View File

@ -12,14 +12,15 @@ use ide_db::{
RootDatabase, SymbolKind,
};
use itertools::Itertools;
use rustc_hash::FxHashSet;
use stdx::always;
use rustc_hash::{FxHashMap, FxHashSet};
use stdx::{always, format_to};
use syntax::ast::{self, AstNode, AttrsOwner};
use crate::{display::TryToNav, references, FileId, NavigationTarget};
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Runnable {
pub use_name_in_title: bool,
pub nav: NavigationTarget,
pub kind: RunnableKind,
pub cfg: Option<CfgExpr>,
@ -49,20 +50,16 @@ pub enum RunnableKind {
Bin,
}
#[derive(Debug, Eq, PartialEq)]
pub struct RunnableAction {
pub run_title: &'static str,
pub debugee: bool,
#[cfg(test)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
enum RunnableTestKind {
Test,
TestMod,
DocTest,
Bench,
Bin,
}
const TEST: RunnableAction = RunnableAction { run_title: "\u{fe0e} Run Test", debugee: true };
const TEST_MOD: RunnableAction =
RunnableAction { run_title: "\u{fe0e} Run Tests", debugee: true };
const DOCTEST: RunnableAction =
RunnableAction { run_title: "\u{fe0e} Run Doctest", debugee: false };
const BENCH: RunnableAction = RunnableAction { run_title: "\u{fe0e} Run Bench", debugee: true };
const BIN: RunnableAction = RunnableAction { run_title: "\u{fe0e} Run", debugee: true };
impl Runnable {
// test package::module::testname
pub fn label(&self, target: Option<String>) -> String {
@ -77,13 +74,43 @@ impl Runnable {
}
}
pub fn action(&self) -> &'static RunnableAction {
pub fn debugee(&self) -> bool {
matches!(
&self.kind,
RunnableKind::TestMod { .. }
| RunnableKind::Test { .. }
| RunnableKind::Bench { .. }
| RunnableKind::Bin
)
}
pub fn title(&self) -> String {
let mut s = String::from("\u{fe0e} Run ");
if self.use_name_in_title {
format_to!(s, "{}", self.nav.name);
if !matches!(self.kind, RunnableKind::Bin) {
s.push(' ');
}
}
let suffix = match &self.kind {
RunnableKind::TestMod { .. } => "Tests",
RunnableKind::Test { .. } => "Test",
RunnableKind::DocTest { .. } => "Doctest",
RunnableKind::Bench { .. } => "Bench",
RunnableKind::Bin => return s,
};
s.push_str(suffix);
s
}
#[cfg(test)]
fn test_kind(&self) -> RunnableTestKind {
match &self.kind {
RunnableKind::TestMod { .. } => &TEST_MOD,
RunnableKind::Test { .. } => &TEST,
RunnableKind::DocTest { .. } => &DOCTEST,
RunnableKind::Bench { .. } => &BENCH,
RunnableKind::Bin => &BIN,
RunnableKind::TestMod { .. } => RunnableTestKind::TestMod,
RunnableKind::Test { .. } => RunnableTestKind::Test,
RunnableKind::DocTest { .. } => RunnableTestKind::DocTest,
RunnableKind::Bench { .. } => RunnableTestKind::Bench,
RunnableKind::Bin => RunnableTestKind::Bin,
}
}
}
@ -104,7 +131,10 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
let sema = Semantics::new(db);
let mut res = Vec::new();
let mut add_opt = |runnable: Option<Runnable>| {
// Record all runnables that come from macro expansions here instead.
// In case an expansion creates multiple runnables we want to name them to avoid emitting a bunch of equally named runnables.
let mut in_macro_expansion = FxHashMap::<hir::HirFileId, Vec<Runnable>>::default();
let mut add_opt = |runnable: Option<Runnable>, def| {
if let Some(runnable) = runnable.filter(|runnable| {
always!(
runnable.nav.file_id == file_id,
@ -113,6 +143,17 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
file_id
)
}) {
if let Some(def) = def {
let file_id = match def {
hir::ModuleDef::Module(it) => it.declaration_source(db).map(|src| src.file_id),
hir::ModuleDef::Function(it) => it.source(db).map(|src| src.file_id),
_ => None,
};
if let Some(file_id) = file_id.filter(|file| file.call_node(db).is_some()) {
in_macro_expansion.entry(file_id).or_default().push(runnable);
return;
}
}
res.push(runnable);
}
};
@ -123,23 +164,35 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
hir::ModuleDef::Function(it) => runnable_fn(&sema, it),
_ => None,
};
add_opt(runnable.or_else(|| module_def_doctest(&sema, def)));
add_opt(runnable.or_else(|| module_def_doctest(&sema, def)), Some(def));
}
Either::Right(impl_) => {
add_opt(runnable_impl(&sema, &impl_));
add_opt(runnable_impl(&sema, &impl_), None);
impl_
.items(db)
.into_iter()
.map(|assoc| match assoc {
hir::AssocItem::Function(it) => {
runnable_fn(&sema, it).or_else(|| module_def_doctest(&sema, it.into()))
}
hir::AssocItem::Const(it) => module_def_doctest(&sema, it.into()),
hir::AssocItem::TypeAlias(it) => module_def_doctest(&sema, it.into()),
.map(|assoc| {
(
match assoc {
hir::AssocItem::Function(it) => runnable_fn(&sema, it)
.or_else(|| module_def_doctest(&sema, it.into())),
hir::AssocItem::Const(it) => module_def_doctest(&sema, it.into()),
hir::AssocItem::TypeAlias(it) => module_def_doctest(&sema, it.into()),
},
assoc,
)
})
.for_each(|r| add_opt(r));
.for_each(|(r, assoc)| add_opt(r, Some(assoc.into())));
}
});
res.extend(in_macro_expansion.into_iter().flat_map(|(_, runnables)| {
let use_name_in_title = runnables.len() != 1;
runnables.into_iter().map(move |mut r| {
r.use_name_in_title = use_name_in_title;
r
})
}));
res
}
@ -272,7 +325,7 @@ pub(crate) fn runnable_fn(sema: &Semantics<RootDatabase>, def: hir::Function) ->
SymbolKind::Function,
);
let cfg = def.attrs(sema.db).cfg();
Some(Runnable { nav, kind, cfg })
Some(Runnable { use_name_in_title: false, nav, kind, cfg })
}
pub(crate) fn runnable_mod(sema: &Semantics<RootDatabase>, def: hir::Module) -> Option<Runnable> {
@ -285,7 +338,7 @@ pub(crate) fn runnable_mod(sema: &Semantics<RootDatabase>, def: hir::Module) ->
let attrs = def.attrs(sema.db);
let cfg = attrs.cfg();
let nav = NavigationTarget::from_module_to_decl(sema.db, def);
Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg })
Some(Runnable { use_name_in_title: false, nav, kind: RunnableKind::TestMod { path }, cfg })
}
pub(crate) fn runnable_impl(sema: &Semantics<RootDatabase>, def: &hir::Impl) -> Option<Runnable> {
@ -305,7 +358,7 @@ pub(crate) fn runnable_impl(sema: &Semantics<RootDatabase>, def: &hir::Impl) ->
};
let test_id = TestId::Path(format!("{}{}", adt_name, params));
Some(Runnable { nav, kind: RunnableKind::DocTest { test_id }, cfg })
Some(Runnable { use_name_in_title: false, nav, kind: RunnableKind::DocTest { test_id }, cfg })
}
fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Option<Runnable> {
@ -368,7 +421,12 @@ fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Op
nav.description = None;
nav.docs = None;
nav.kind = None;
let res = Runnable { nav, kind: RunnableKind::DocTest { test_id }, cfg: attrs.cfg() };
let res = Runnable {
use_name_in_title: false,
nav,
kind: RunnableKind::DocTest { test_id },
cfg: attrs.cfg(),
};
Some(res)
}
@ -448,12 +506,12 @@ mod tests {
use crate::fixture;
use super::*;
use super::{RunnableTestKind::*, *};
fn check(
ra_fixture: &str,
// FIXME: fold this into `expect` as well
actions: &[&RunnableAction],
actions: &[RunnableTestKind],
expect: Expect,
) {
let (analysis, position) = fixture::position(ra_fixture);
@ -461,7 +519,7 @@ mod tests {
expect.assert_debug_eq(&runnables);
assert_eq!(
actions,
runnables.into_iter().map(|it| it.action()).collect::<Vec<_>>().as_slice()
runnables.into_iter().map(|it| it.test_kind()).collect::<Vec<_>>().as_slice()
);
}
@ -493,10 +551,11 @@ mod not_a_root {
fn main() {}
}
"#,
&[&BIN, &TEST, &TEST, &BENCH],
&[Bin, Test, Test, Bench],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -510,6 +569,7 @@ mod not_a_root {
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -530,6 +590,7 @@ mod not_a_root {
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -550,6 +611,7 @@ mod not_a_root {
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -667,10 +729,11 @@ trait Test {
/// ```
impl Test for StructWithRunnable {}
"#,
&[&BIN, &DOCTEST, &DOCTEST, &DOCTEST, &DOCTEST, &DOCTEST, &DOCTEST, &DOCTEST, &DOCTEST],
&[Bin, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -684,6 +747,7 @@ impl Test for StructWithRunnable {}
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -699,6 +763,7 @@ impl Test for StructWithRunnable {}
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -714,6 +779,7 @@ impl Test for StructWithRunnable {}
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -729,6 +795,7 @@ impl Test for StructWithRunnable {}
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -744,6 +811,7 @@ impl Test for StructWithRunnable {}
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -759,6 +827,7 @@ impl Test for StructWithRunnable {}
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -774,6 +843,7 @@ impl Test for StructWithRunnable {}
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -791,6 +861,7 @@ impl Test for StructWithRunnable {}
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -828,10 +899,11 @@ impl Data {
fn foo() {}
}
"#,
&[&BIN, &DOCTEST],
&[Bin, DocTest],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -845,6 +917,7 @@ impl Data {
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -875,10 +948,11 @@ mod test_mod {
fn test_foo1() {}
}
"#,
&[&TEST_MOD, &TEST],
&[TestMod, Test],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -895,6 +969,7 @@ mod test_mod {
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -946,10 +1021,11 @@ mod root_tests {
mod nested_tests_4 {}
}
"#,
&[&TEST_MOD, &TEST_MOD, &TEST_MOD, &TEST, &TEST, &TEST],
&[TestMod, TestMod, TestMod, Test, Test, Test],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -966,6 +1042,7 @@ mod root_tests {
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -982,6 +1059,7 @@ mod root_tests {
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -998,6 +1076,7 @@ mod root_tests {
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -1018,6 +1097,7 @@ mod root_tests {
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -1038,6 +1118,7 @@ mod root_tests {
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -1072,10 +1153,11 @@ $0
#[cfg(feature = "foo")]
fn test_foo1() {}
"#,
&[&TEST],
&[Test],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -1117,10 +1199,11 @@ $0
#[cfg(all(feature = "foo", feature = "bar"))]
fn test_foo1() {}
"#,
&[&TEST],
&[Test],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -1194,10 +1277,11 @@ impl Foo {
fn foo() {}
}
"#,
&[&DOCTEST],
&[DocTest],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
1,
@ -1231,9 +1315,9 @@ macro_rules! gen {
}
macro_rules! gen2 {
() => {
mod m_tests {
mod tests2 {
#[test]
fn foo_test() {}
fn foo_test2() {}
}
}
}
@ -1242,10 +1326,11 @@ mod tests {
}
gen2!();
"#,
&[&TEST_MOD, &TEST_MOD, &TEST, &TEST],
&[TestMod, TestMod, Test, Test],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -1262,22 +1347,45 @@ gen2!();
cfg: None,
},
Runnable {
use_name_in_title: true,
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 228..236,
focus_range: 228..236,
name: "m_tests",
name: "tests2",
kind: Module,
description: "mod m_tests",
description: "mod tests2",
},
kind: TestMod {
path: "m_tests",
path: "tests2",
},
cfg: None,
},
Runnable {
use_name_in_title: true,
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 228..236,
focus_range: 228..236,
name: "foo_test2",
kind: Function,
},
kind: Test {
test_id: Path(
"tests2::foo_test2",
),
attr: TestAttr {
ignore: false,
},
},
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -1297,19 +1405,107 @@ gen2!();
},
cfg: None,
},
]
"#]],
);
}
#[test]
fn big_mac() {
check(
r#"
//- /lib.rs
$0
macro_rules! foo {
() => {
mod foo_tests {
#[test]
fn foo0() {}
#[test]
fn foo1() {}
#[test]
fn foo2() {}
}
};
}
foo!();
"#,
&[TestMod, Test, Test, Test],
expect![[r#"
[
Runnable {
use_name_in_title: true,
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 228..236,
focus_range: 228..236,
name: "foo_test",
full_range: 210..217,
focus_range: 210..217,
name: "foo_tests",
kind: Module,
description: "mod foo_tests",
},
kind: TestMod {
path: "foo_tests",
},
cfg: None,
},
Runnable {
use_name_in_title: true,
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 210..217,
focus_range: 210..217,
name: "foo0",
kind: Function,
},
kind: Test {
test_id: Path(
"m_tests::foo_test",
"foo_tests::foo0",
),
attr: TestAttr {
ignore: false,
},
},
cfg: None,
},
Runnable {
use_name_in_title: true,
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 210..217,
focus_range: 210..217,
name: "foo1",
kind: Function,
},
kind: Test {
test_id: Path(
"foo_tests::foo1",
),
attr: TestAttr {
ignore: false,
},
},
cfg: None,
},
Runnable {
use_name_in_title: true,
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 210..217,
focus_range: 210..217,
name: "foo2",
kind: Function,
},
kind: Test {
test_id: Path(
"foo_tests::foo2",
),
attr: TestAttr {
ignore: false,
@ -1355,10 +1551,11 @@ fn t0() {}
#[test]
fn t1() {}
"#,
&[&TEST_MOD],
&[TestMod],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -1392,10 +1589,11 @@ fn t0() {}
#[test]
fn t1() {}
"#,
&[&TEST, &TEST],
&[Test, Test],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
1,
@ -1416,6 +1614,7 @@ fn t1() {}
cfg: None,
},
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
1,
@ -1470,6 +1669,7 @@ mod tests {
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -1512,28 +1712,29 @@ mod tests {
}
"#,
expect![[r#"
[
Runnable {
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 71..122,
focus_range: 86..94,
name: "foo_test",
kind: Function,
},
kind: Test {
test_id: Path(
"tests::foo_test",
),
attr: TestAttr {
ignore: false,
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 71..122,
focus_range: 86..94,
name: "foo_test",
kind: Function,
},
kind: Test {
test_id: Path(
"tests::foo_test",
),
attr: TestAttr {
ignore: false,
},
},
cfg: None,
},
cfg: None,
},
]
]
"#]],
);
}
@ -1565,6 +1766,7 @@ mod tests {
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
@ -1614,48 +1816,50 @@ mod tests {
}
"#,
expect![[r#"
[
Runnable {
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 52..115,
focus_range: 67..75,
name: "foo_test",
kind: Function,
},
kind: Test {
test_id: Path(
"tests::foo_test",
),
attr: TestAttr {
ignore: false,
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 52..115,
focus_range: 67..75,
name: "foo_test",
kind: Function,
},
},
cfg: None,
},
Runnable {
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 121..185,
focus_range: 136..145,
name: "foo2_test",
kind: Function,
},
kind: Test {
test_id: Path(
"tests::foo2_test",
),
attr: TestAttr {
ignore: false,
kind: Test {
test_id: Path(
"tests::foo_test",
),
attr: TestAttr {
ignore: false,
},
},
cfg: None,
},
cfg: None,
},
]
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 121..185,
focus_range: 136..145,
name: "foo2_test",
kind: Function,
},
kind: Test {
test_id: Path(
"tests::foo2_test",
),
attr: TestAttr {
ignore: false,
},
},
cfg: None,
},
]
"#]],
);
}
@ -1674,10 +1878,11 @@ impl<T, U> Foo<T, U> {
fn t() {}
}
"#,
&[&DOCTEST],
&[DocTest],
expect![[r#"
[
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,

View File

@ -1542,12 +1542,12 @@ fn runnable_action_links(
return None;
}
let action: &'static _ = runnable.action();
let title = runnable.title();
to_proto::runnable(snap, runnable).ok().map(|r| {
let mut group = lsp_ext::CommandLinkGroup::default();
if hover_actions_config.run {
let run_command = to_proto::command::run_single(&r, action.run_title);
let run_command = to_proto::command::run_single(&r, &title);
group.commands.push(to_command_link(run_command, r.label.clone()));
}

View File

@ -996,15 +996,11 @@ 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 action = run.action();
let title = run.title();
let r = runnable(snap, run)?;
let command = if debug {
command::debug_single(&r)
} else {
let title = action.run_title.to_string();
command::run_single(&r, &title)
};
let command =
if debug { command::debug_single(&r) } else { command::run_single(&r, &title) };
Ok(lsp_types::CodeLens { range: annotation_range, command: Some(command), data: None })
}