Don't add test runnables for outline modules in the wrong file

This commit is contained in:
Lukas Wirth 2021-06-30 19:08:13 +02:00
parent 1b9b2d1f40
commit b8507ca98d
3 changed files with 139 additions and 18 deletions

View file

@ -862,6 +862,7 @@ mod tests {
focus_range: 18..23, focus_range: 18..23,
name: "tests", name: "tests",
kind: Module, kind: Module,
description: "mod tests",
}, },
kind: TestMod { kind: TestMod {
path: "tests", path: "tests",
@ -883,6 +884,7 @@ mod tests {
focus_range: 18..23, focus_range: 18..23,
name: "tests", name: "tests",
kind: Module, kind: Module,
description: "mod tests",
}, },
kind: TestMod { kind: TestMod {
path: "tests", path: "tests",

View file

@ -2508,6 +2508,7 @@ mod tests$0 {
focus_range: 4..9, focus_range: 4..9,
name: "tests", name: "tests",
kind: Module, kind: Module,
description: "mod tests",
}, },
kind: TestMod { kind: TestMod {
path: "tests", path: "tests",

View file

@ -13,12 +13,10 @@ use ide_db::{
}; };
use itertools::Itertools; use itertools::Itertools;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use stdx::always;
use syntax::ast::{self, AstNode, AttrsOwner}; use syntax::ast::{self, AstNode, AttrsOwner};
use crate::{ use crate::{display::TryToNav, references, FileId, NavigationTarget};
display::{ToNav, TryToNav},
references, FileId, NavigationTarget,
};
#[derive(Debug, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Runnable { pub struct Runnable {
@ -58,6 +56,8 @@ pub struct RunnableAction {
} }
const TEST: RunnableAction = RunnableAction { run_title: "\u{fe0e} Run Test", debugee: true }; 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 = const DOCTEST: RunnableAction =
RunnableAction { run_title: "\u{fe0e} Run Doctest", debugee: false }; RunnableAction { run_title: "\u{fe0e} Run Doctest", debugee: false };
const BENCH: RunnableAction = RunnableAction { run_title: "\u{fe0e} Run Bench", debugee: true }; const BENCH: RunnableAction = RunnableAction { run_title: "\u{fe0e} Run Bench", debugee: true };
@ -79,7 +79,8 @@ impl Runnable {
pub fn action(&self) -> &'static RunnableAction { pub fn action(&self) -> &'static RunnableAction {
match &self.kind { match &self.kind {
RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => &TEST, RunnableKind::TestMod { .. } => &TEST_MOD,
RunnableKind::Test { .. } => &TEST,
RunnableKind::DocTest { .. } => &DOCTEST, RunnableKind::DocTest { .. } => &DOCTEST,
RunnableKind::Bench { .. } => &BENCH, RunnableKind::Bench { .. } => &BENCH,
RunnableKind::Bin => &BIN, RunnableKind::Bin => &BIN,
@ -103,6 +104,16 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
let sema = Semantics::new(db); let sema = Semantics::new(db);
let mut res = Vec::new(); let mut res = Vec::new();
let mut add_opt = |runnable: Option<Runnable>| {
if let Some(runnable) = runnable.filter(|r| {
always!(
r.nav.file_id == file_id,
"tried adding a runnable pointing to a different file"
)
}) {
res.push(runnable);
}
};
visit_file_defs(&sema, file_id, &mut |def| match def { visit_file_defs(&sema, file_id, &mut |def| match def {
Either::Left(def) => { Either::Left(def) => {
let runnable = match def { let runnable = match def {
@ -110,17 +121,21 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
hir::ModuleDef::Function(it) => runnable_fn(&sema, it), hir::ModuleDef::Function(it) => runnable_fn(&sema, it),
_ => None, _ => None,
}; };
res.extend(runnable.or_else(|| module_def_doctest(&sema, def))) add_opt(runnable.or_else(|| module_def_doctest(&sema, def)));
} }
Either::Right(impl_) => { Either::Right(impl_) => {
res.extend(runnable_impl(&sema, &impl_)); add_opt(runnable_impl(&sema, &impl_));
res.extend(impl_.items(db).into_iter().filter_map(|assoc| match assoc { impl_
hir::AssocItem::Function(it) => { .items(db)
runnable_fn(&sema, it).or_else(|| module_def_doctest(&sema, it.into())) .into_iter()
} .map(|assoc| match assoc {
hir::AssocItem::Const(it) => module_def_doctest(&sema, it.into()), hir::AssocItem::Function(it) => {
hir::AssocItem::TypeAlias(it) => module_def_doctest(&sema, it.into()), 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()),
})
.for_each(|r| add_opt(r));
} }
}); });
res res
@ -267,7 +282,7 @@ pub(crate) fn runnable_mod(sema: &Semantics<RootDatabase>, def: hir::Module) ->
let attrs = def.attrs(sema.db); let attrs = def.attrs(sema.db);
let cfg = attrs.cfg(); let cfg = attrs.cfg();
let nav = def.to_nav(sema.db); let nav = NavigationTarget::from_module_to_decl(sema.db, def);
Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg }) Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg })
} }
@ -855,7 +870,7 @@ mod test_mod {
fn test_foo1() {} fn test_foo1() {}
} }
"#, "#,
&[&TEST, &TEST], &[&TEST_MOD, &TEST],
expect![[r#" expect![[r#"
[ [
Runnable { Runnable {
@ -867,6 +882,7 @@ mod test_mod {
focus_range: 5..13, focus_range: 5..13,
name: "test_mod", name: "test_mod",
kind: Module, kind: Module,
description: "mod test_mod",
}, },
kind: TestMod { kind: TestMod {
path: "test_mod", path: "test_mod",
@ -925,7 +941,7 @@ mod root_tests {
mod nested_tests_4 {} mod nested_tests_4 {}
} }
"#, "#,
&[&TEST, &TEST, &TEST, &TEST, &TEST, &TEST], &[&TEST_MOD, &TEST_MOD, &TEST_MOD, &TEST, &TEST, &TEST],
expect![[r#" expect![[r#"
[ [
Runnable { Runnable {
@ -937,6 +953,7 @@ mod root_tests {
focus_range: 26..40, focus_range: 26..40,
name: "nested_tests_0", name: "nested_tests_0",
kind: Module, kind: Module,
description: "mod nested_tests_0",
}, },
kind: TestMod { kind: TestMod {
path: "root_tests::nested_tests_0", path: "root_tests::nested_tests_0",
@ -952,6 +969,7 @@ mod root_tests {
focus_range: 55..69, focus_range: 55..69,
name: "nested_tests_1", name: "nested_tests_1",
kind: Module, kind: Module,
description: "mod nested_tests_1",
}, },
kind: TestMod { kind: TestMod {
path: "root_tests::nested_tests_0::nested_tests_1", path: "root_tests::nested_tests_0::nested_tests_1",
@ -967,6 +985,7 @@ mod root_tests {
focus_range: 206..220, focus_range: 206..220,
name: "nested_tests_2", name: "nested_tests_2",
kind: Module, kind: Module,
description: "mod nested_tests_2",
}, },
kind: TestMod { kind: TestMod {
path: "root_tests::nested_tests_0::nested_tests_2", path: "root_tests::nested_tests_0::nested_tests_2",
@ -1210,7 +1229,7 @@ mod tests {
gen!(); gen!();
} }
"#, "#,
&[&TEST, &TEST], &[&TEST_MOD, &TEST],
expect![[r#" expect![[r#"
[ [
Runnable { Runnable {
@ -1222,6 +1241,7 @@ mod tests {
focus_range: 94..99, focus_range: 94..99,
name: "tests", name: "tests",
kind: Module, kind: Module,
description: "mod tests",
}, },
kind: TestMod { kind: TestMod {
path: "tests", path: "tests",
@ -1273,6 +1293,104 @@ mod tests {
); );
} }
#[test]
fn outline_submodule1() {
check(
r#"
//- /lib.rs
$0
mod m;
//- /m.rs
#[test]
fn t0() {}
#[test]
fn t1() {}
"#,
&[&TEST_MOD],
expect![[r#"
[
Runnable {
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 1..7,
focus_range: 5..6,
name: "m",
kind: Module,
description: "mod m",
},
kind: TestMod {
path: "m",
},
cfg: None,
},
]
"#]],
);
}
#[test]
fn outline_submodule2() {
check(
r#"
//- /lib.rs
mod m;
//- /m.rs
$0
#[test]
fn t0() {}
#[test]
fn t1() {}
"#,
&[&TEST, &TEST],
expect![[r#"
[
Runnable {
nav: NavigationTarget {
file_id: FileId(
1,
),
full_range: 1..19,
focus_range: 12..14,
name: "t0",
kind: Function,
},
kind: Test {
test_id: Path(
"m::t0",
),
attr: TestAttr {
ignore: false,
},
},
cfg: None,
},
Runnable {
nav: NavigationTarget {
file_id: FileId(
1,
),
full_range: 20..38,
focus_range: 31..33,
name: "t1",
kind: Function,
},
kind: Test {
test_id: Path(
"m::t1",
),
attr: TestAttr {
ignore: false,
},
},
cfg: None,
},
]
"#]],
);
}
#[test] #[test]
fn find_no_tests() { fn find_no_tests() {
check_tests( check_tests(