5 use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics};
6 use ide_assists::utils::test_related_attribute;
8 base_db::{FilePosition, FileRange},
10 helpers::visit_file_defs,
12 FxHashMap, FxHashSet, RootDatabase, SymbolKind,
14 use itertools::Itertools;
15 use stdx::{always, format_to};
17 ast::{self, AstNode, HasAttrs as _},
21 use crate::{references, FileId, NavigationTarget, ToNav, TryToNav};
23 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
25 pub use_name_in_title: bool,
26 pub nav: NavigationTarget,
27 pub kind: RunnableKind,
28 pub cfg: Option<CfgExpr>,
31 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
37 impl fmt::Display for TestId {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 TestId::Name(name) => name.fmt(f),
41 TestId::Path(path) => path.fmt(f),
46 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
47 pub enum RunnableKind {
48 Test { test_id: TestId, attr: TestAttr },
49 TestMod { path: String },
50 Bench { test_id: TestId },
51 DocTest { test_id: TestId },
56 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
57 enum RunnableTestKind {
66 // test package::module::testname
67 pub fn label(&self, target: Option<String>) -> String {
69 RunnableKind::Test { test_id, .. } => format!("test {}", test_id),
70 RunnableKind::TestMod { path } => format!("test-mod {}", path),
71 RunnableKind::Bench { test_id } => format!("bench {}", test_id),
72 RunnableKind::DocTest { test_id, .. } => format!("doctest {}", test_id),
73 RunnableKind::Bin => {
74 target.map_or_else(|| "run binary".to_string(), |t| format!("run {}", t))
79 pub fn title(&self) -> String {
80 let mut s = String::from("▶\u{fe0e} Run ");
81 if self.use_name_in_title {
82 format_to!(s, "{}", self.nav.name);
83 if !matches!(self.kind, RunnableKind::Bin) {
87 let suffix = match &self.kind {
88 RunnableKind::TestMod { .. } => "Tests",
89 RunnableKind::Test { .. } => "Test",
90 RunnableKind::DocTest { .. } => "Doctest",
91 RunnableKind::Bench { .. } => "Bench",
92 RunnableKind::Bin => return s,
99 fn test_kind(&self) -> RunnableTestKind {
101 RunnableKind::TestMod { .. } => RunnableTestKind::TestMod,
102 RunnableKind::Test { .. } => RunnableTestKind::Test,
103 RunnableKind::DocTest { .. } => RunnableTestKind::DocTest,
104 RunnableKind::Bench { .. } => RunnableTestKind::Bench,
105 RunnableKind::Bin => RunnableTestKind::Bin,
112 // Shows a popup suggesting to run a test/benchmark/binary **at the current cursor
113 // location**. Super useful for repeatedly running just a single test. Do bind this
117 // | Editor | Action Name
119 // | VS Code | **rust-analyzer: Run**
121 // image::https://user-images.githubusercontent.com/48062697/113065583-055aae80-91b1-11eb-958f-d67efcaf6a2f.gif[]
122 pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
123 let sema = Semantics::new(db);
125 let mut res = Vec::new();
126 // Record all runnables that come from macro expansions here instead.
127 // In case an expansion creates multiple runnables we want to name them to avoid emitting a bunch of equally named runnables.
128 let mut in_macro_expansion = FxHashMap::<hir::HirFileId, Vec<Runnable>>::default();
129 let mut add_opt = |runnable: Option<Runnable>, def| {
130 if let Some(runnable) = runnable.filter(|runnable| {
132 runnable.nav.file_id == file_id,
133 "tried adding a runnable pointing to a different file: {:?} for {:?}",
138 if let Some(def) = def {
139 let file_id = match def {
140 Definition::Module(it) => it.declaration_source(db).map(|src| src.file_id),
141 Definition::Function(it) => it.source(db).map(|src| src.file_id),
144 if let Some(file_id) = file_id.filter(|file| file.call_node(db).is_some()) {
145 in_macro_expansion.entry(file_id).or_default().push(runnable);
152 visit_file_defs(&sema, file_id, &mut |def| {
153 let runnable = match def {
154 Definition::Module(it) => runnable_mod(&sema, it),
155 Definition::Function(it) => runnable_fn(&sema, it),
156 Definition::SelfType(impl_) => runnable_impl(&sema, &impl_),
161 .or_else(|| module_def_doctest(sema.db, def))
162 // #[macro_export] mbe macros are declared in the root, while their definition may reside in a different module
163 .filter(|it| it.nav.file_id == file_id),
166 if let Definition::SelfType(impl_) = def {
167 impl_.items(db).into_iter().for_each(|assoc| {
168 let runnable = match assoc {
169 hir::AssocItem::Function(it) => {
170 runnable_fn(&sema, it).or_else(|| module_def_doctest(sema.db, it.into()))
172 hir::AssocItem::Const(it) => module_def_doctest(sema.db, it.into()),
173 hir::AssocItem::TypeAlias(it) => module_def_doctest(sema.db, it.into()),
175 add_opt(runnable, Some(assoc.into()))
180 sema.to_module_defs(file_id)
181 .map(|it| runnable_mod_outline_definition(&sema, it))
182 .for_each(|it| add_opt(it, None));
184 res.extend(in_macro_expansion.into_iter().flat_map(|(_, runnables)| {
185 let use_name_in_title = runnables.len() != 1;
186 runnables.into_iter().map(move |mut r| {
187 r.use_name_in_title = use_name_in_title;
194 // Feature: Related Tests
196 // Provides a sneak peek of all tests where the current item is used.
198 // The simplest way to use this feature is via the context menu:
199 // - Right-click on the selected item. The context menu opens.
200 // - Select **Peek related tests**
203 // | Editor | Action Name
205 // | VS Code | **rust-analyzer: Peek related tests**
207 pub(crate) fn related_tests(
209 position: FilePosition,
210 search_scope: Option<SearchScope>,
212 let sema = Semantics::new(db);
213 let mut res: FxHashSet<Runnable> = FxHashSet::default();
214 let syntax = sema.parse(position.file_id).syntax().clone();
216 find_related_tests(&sema, &syntax, position, search_scope, &mut res);
218 res.into_iter().collect()
221 fn find_related_tests(
222 sema: &Semantics<'_, RootDatabase>,
224 position: FilePosition,
225 search_scope: Option<SearchScope>,
226 tests: &mut FxHashSet<Runnable>,
228 // FIXME: why is this using references::find_defs, this should use ide_db::search
229 let defs = match references::find_defs(sema, syntax, position.offset) {
236 .set_scope(search_scope.clone())
242 let name_ref = match ref_.name {
243 ast::NameLike::NameRef(name_ref) => name_ref,
246 if let Some(fn_def) =
247 sema.ancestors_with_macros(name_ref.syntax().clone()).find_map(ast::Fn::cast)
249 if let Some(runnable) = as_test_runnable(sema, &fn_def) {
251 tests.insert(runnable);
252 } else if let Some(module) = parent_test_module(sema, &fn_def) {
254 find_related_tests_in_module(sema, syntax, &fn_def, &module, tests);
261 fn find_related_tests_in_module(
262 sema: &Semantics<'_, RootDatabase>,
265 parent_module: &hir::Module,
266 tests: &mut FxHashSet<Runnable>,
268 let fn_name = match fn_def.name() {
272 let mod_source = parent_module.definition_source(sema.db);
273 let range = match &mod_source.value {
274 hir::ModuleSource::Module(m) => m.syntax().text_range(),
275 hir::ModuleSource::BlockExpr(b) => b.syntax().text_range(),
276 hir::ModuleSource::SourceFile(f) => f.syntax().text_range(),
279 let file_id = mod_source.file_id.original_file(sema.db);
280 let mod_scope = SearchScope::file_range(FileRange { file_id, range });
281 let fn_pos = FilePosition { file_id, offset: fn_name.syntax().text_range().start() };
282 find_related_tests(sema, syntax, fn_pos, Some(mod_scope), tests)
285 fn as_test_runnable(sema: &Semantics<'_, RootDatabase>, fn_def: &ast::Fn) -> Option<Runnable> {
286 if test_related_attribute(fn_def).is_some() {
287 let function = sema.to_def(fn_def)?;
288 runnable_fn(sema, function)
294 fn parent_test_module(sema: &Semantics<'_, RootDatabase>, fn_def: &ast::Fn) -> Option<hir::Module> {
295 fn_def.syntax().ancestors().find_map(|node| {
296 let module = ast::Module::cast(node)?;
297 let module = sema.to_def(&module)?;
299 if has_test_function_or_multiple_test_submodules(sema, &module) {
307 pub(crate) fn runnable_fn(
308 sema: &Semantics<'_, RootDatabase>,
310 ) -> Option<Runnable> {
311 let func = def.source(sema.db)?;
312 let name = def.name(sema.db).to_smol_str();
314 let root = def.module(sema.db).krate().root_module(sema.db);
316 let kind = if name == "main" && def.module(sema.db) == root {
320 let canonical_path = {
321 let def: hir::ModuleDef = def.into();
322 def.canonical_path(sema.db)
324 canonical_path.map(TestId::Path).unwrap_or(TestId::Name(name))
327 if test_related_attribute(&func.value).is_some() {
328 let attr = TestAttr::from_fn(&func.value);
329 RunnableKind::Test { test_id: test_id(), attr }
330 } else if func.value.has_atom_attr("bench") {
331 RunnableKind::Bench { test_id: test_id() }
337 let nav = NavigationTarget::from_named(
339 func.as_ref().map(|it| it as &dyn ast::HasName),
340 SymbolKind::Function,
342 let cfg = def.attrs(sema.db).cfg();
343 Some(Runnable { use_name_in_title: false, nav, kind, cfg })
346 pub(crate) fn runnable_mod(
347 sema: &Semantics<'_, RootDatabase>,
349 ) -> Option<Runnable> {
350 if !has_test_function_or_multiple_test_submodules(sema, &def) {
354 def.path_to_root(sema.db).into_iter().rev().filter_map(|it| it.name(sema.db)).join("::");
356 let attrs = def.attrs(sema.db);
357 let cfg = attrs.cfg();
358 let nav = NavigationTarget::from_module_to_decl(sema.db, def);
359 Some(Runnable { use_name_in_title: false, nav, kind: RunnableKind::TestMod { path }, cfg })
362 pub(crate) fn runnable_impl(
363 sema: &Semantics<'_, RootDatabase>,
365 ) -> Option<Runnable> {
366 let attrs = def.attrs(sema.db);
367 if !has_runnable_doc_test(&attrs) {
370 let cfg = attrs.cfg();
371 let nav = def.try_to_nav(sema.db)?;
372 let ty = def.self_ty(sema.db);
373 let adt_name = ty.as_adt()?.name(sema.db);
374 let mut ty_args = ty.type_arguments().peekable();
375 let params = if ty_args.peek().is_some() {
376 format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty.display(sema.db))))
380 let mut test_id = format!("{}{}", adt_name, params);
381 test_id.retain(|c| c != ' ');
382 let test_id = TestId::Path(test_id);
384 Some(Runnable { use_name_in_title: false, nav, kind: RunnableKind::DocTest { test_id }, cfg })
387 /// Creates a test mod runnable for outline modules at the top of their definition.
388 fn runnable_mod_outline_definition(
389 sema: &Semantics<'_, RootDatabase>,
391 ) -> Option<Runnable> {
392 if !has_test_function_or_multiple_test_submodules(sema, &def) {
396 def.path_to_root(sema.db).into_iter().rev().filter_map(|it| it.name(sema.db)).join("::");
398 let attrs = def.attrs(sema.db);
399 let cfg = attrs.cfg();
400 match def.definition_source(sema.db).value {
401 hir::ModuleSource::SourceFile(_) => Some(Runnable {
402 use_name_in_title: false,
403 nav: def.to_nav(sema.db),
404 kind: RunnableKind::TestMod { path },
411 fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
412 let attrs = match def {
413 Definition::Module(it) => it.attrs(db),
414 Definition::Function(it) => it.attrs(db),
415 Definition::Adt(it) => it.attrs(db),
416 Definition::Variant(it) => it.attrs(db),
417 Definition::Const(it) => it.attrs(db),
418 Definition::Static(it) => it.attrs(db),
419 Definition::Trait(it) => it.attrs(db),
420 Definition::TypeAlias(it) => it.attrs(db),
421 Definition::Macro(it) => it.attrs(db),
422 Definition::SelfType(it) => it.attrs(db),
425 if !has_runnable_doc_test(&attrs) {
428 let def_name = def.name(db)?;
430 let mut path = String::new();
431 def.canonical_module_path(db)?
432 .flat_map(|it| it.name(db))
433 .for_each(|name| format_to!(path, "{}::", name));
434 // This probably belongs to canonical_path?
435 if let Some(assoc_item) = def.as_assoc_item(db) {
436 if let hir::AssocItemContainer::Impl(imp) = assoc_item.container(db) {
437 let ty = imp.self_ty(db);
438 if let Some(adt) = ty.as_adt() {
439 let name = adt.name(db);
440 let mut ty_args = ty.type_arguments().peekable();
441 format_to!(path, "{}", name);
442 if ty_args.peek().is_some() {
446 ty_args.format_with(",", |ty, cb| cb(&ty.display(db)))
449 format_to!(path, "::{}", def_name);
450 path.retain(|c| c != ' ');
455 format_to!(path, "{}", def_name);
459 let test_id = path.map_or_else(|| TestId::Name(def_name.to_smol_str()), TestId::Path);
461 let mut nav = match def {
462 Definition::Module(def) => NavigationTarget::from_module_to_decl(db, def),
463 def => def.try_to_nav(db)?,
465 nav.focus_range = None;
466 nav.description = None;
470 use_name_in_title: false,
472 kind: RunnableKind::DocTest { test_id },
478 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
479 pub struct TestAttr {
484 fn from_fn(fn_def: &ast::Fn) -> TestAttr {
487 .filter_map(|attr| attr.simple_name())
488 .any(|attribute_text| attribute_text == "ignore");
493 const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"];
494 const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
495 &["", "rust", "should_panic", "edition2015", "edition2018", "edition2021"];
497 fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool {
498 attrs.docs().map_or(false, |doc| {
499 let mut in_code_block = false;
501 for line in String::from(doc).lines() {
502 if let Some(header) =
503 RUSTDOC_FENCES.into_iter().find_map(|fence| line.strip_prefix(fence))
505 in_code_block = !in_code_block;
510 .all(|sub| RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE.contains(&sub.trim()))
521 // We could create runnables for modules with number_of_test_submodules > 0,
522 // but that bloats the runnables for no real benefit, since all tests can be run by the submodule already
523 fn has_test_function_or_multiple_test_submodules(
524 sema: &Semantics<'_, RootDatabase>,
525 module: &hir::Module,
527 let mut number_of_test_submodules = 0;
529 for item in module.declarations(sema.db) {
531 hir::ModuleDef::Function(f) => {
532 if let Some(it) = f.source(sema.db) {
533 if test_related_attribute(&it.value).is_some() {
538 hir::ModuleDef::Module(submodule) => {
539 if has_test_function_or_multiple_test_submodules(sema, &submodule) {
540 number_of_test_submodules += 1;
547 number_of_test_submodules > 1
552 use expect_test::{expect, Expect};
556 use super::{RunnableTestKind::*, *};
560 // FIXME: fold this into `expect` as well
561 actions: &[RunnableTestKind],
564 let (analysis, position) = fixture::position(ra_fixture);
565 let mut runnables = analysis.runnables(position.file_id).unwrap();
566 runnables.sort_by_key(|it| (it.nav.full_range.start(), it.nav.name.clone()));
567 expect.assert_debug_eq(&runnables);
570 runnables.into_iter().map(|it| it.test_kind()).collect::<Vec<_>>().as_slice()
574 fn check_tests(ra_fixture: &str, expect: Expect) {
575 let (analysis, position) = fixture::position(ra_fixture);
576 let tests = analysis.related_tests(position, None).unwrap();
577 expect.assert_debug_eq(&tests);
581 fn test_runnables() {
602 &[TestMod, Bin, Test, Test, Bench],
606 use_name_in_title: false,
607 nav: NavigationTarget {
621 use_name_in_title: false,
622 nav: NavigationTarget {
635 use_name_in_title: false,
636 nav: NavigationTarget {
656 use_name_in_title: false,
657 nav: NavigationTarget {
677 use_name_in_title: false,
678 nav: NavigationTarget {
700 fn test_runnables_doc_test() {
710 fn should_have_runnable() {}
715 fn should_have_runnable_1() {}
724 fn should_have_runnable_2() {}
731 fn should_have_no_runnable_3() {}
738 fn should_have_no_runnable_4() {}
743 fn should_have_no_runnable() {}
748 fn should_have_no_runnable_2() {}
753 fn should_have_no_runnable_3() {}
756 /// arbitrary plain text
758 fn should_have_no_runnable_4() {}
761 /// arbitrary plain text
767 fn should_have_no_runnable_5() {}
772 fn should_have_no_runnable_6() {}
777 struct StructWithRunnable(String);
782 impl StructWithRunnable {}
793 impl Test for StructWithRunnable {}
795 &[Bin, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest],
799 use_name_in_title: false,
800 nav: NavigationTarget {
813 use_name_in_title: false,
814 nav: NavigationTarget {
819 name: "should_have_runnable",
823 "should_have_runnable",
829 use_name_in_title: false,
830 nav: NavigationTarget {
835 name: "should_have_runnable_1",
839 "should_have_runnable_1",
845 use_name_in_title: false,
846 nav: NavigationTarget {
850 full_range: 150..254,
851 name: "should_have_runnable_2",
855 "should_have_runnable_2",
861 use_name_in_title: false,
862 nav: NavigationTarget {
866 full_range: 256..320,
867 name: "should_have_no_runnable_3",
871 "should_have_no_runnable_3",
877 use_name_in_title: false,
878 nav: NavigationTarget {
882 full_range: 322..398,
883 name: "should_have_no_runnable_4",
887 "should_have_no_runnable_4",
893 use_name_in_title: false,
894 nav: NavigationTarget {
898 full_range: 900..965,
899 name: "StructWithRunnable",
903 "StructWithRunnable",
909 use_name_in_title: false,
910 nav: NavigationTarget {
914 full_range: 967..1024,
915 focus_range: 1003..1021,
921 "StructWithRunnable",
927 use_name_in_title: false,
928 nav: NavigationTarget {
932 full_range: 1088..1154,
933 focus_range: 1133..1151,
939 "StructWithRunnable",
950 fn test_runnables_doc_test_in_impl() {
969 use_name_in_title: false,
970 nav: NavigationTarget {
983 use_name_in_title: false,
984 nav: NavigationTarget {
1004 fn test_runnables_module() {
1018 use_name_in_title: false,
1019 nav: NavigationTarget {
1027 description: "mod test_mod",
1035 use_name_in_title: false,
1036 nav: NavigationTarget {
1041 focus_range: 35..44,
1047 "test_mod::test_foo1",
1061 fn only_modules_with_test_functions_or_more_than_one_test_submodule_have_runners() {
1067 mod nested_tests_0 {
1068 mod nested_tests_1 {
1070 fn nested_test_11() {}
1073 fn nested_test_12() {}
1076 mod nested_tests_2 {
1078 fn nested_test_2() {}
1081 mod nested_tests_3 {}
1084 mod nested_tests_4 {}
1087 &[TestMod, TestMod, Test, Test, TestMod, Test],
1091 use_name_in_title: false,
1092 nav: NavigationTarget {
1096 full_range: 22..323,
1097 focus_range: 26..40,
1098 name: "nested_tests_0",
1100 description: "mod nested_tests_0",
1103 path: "root_tests::nested_tests_0",
1108 use_name_in_title: false,
1109 nav: NavigationTarget {
1113 full_range: 51..192,
1114 focus_range: 55..69,
1115 name: "nested_tests_1",
1117 description: "mod nested_tests_1",
1120 path: "root_tests::nested_tests_0::nested_tests_1",
1125 use_name_in_title: false,
1126 nav: NavigationTarget {
1130 full_range: 84..126,
1131 focus_range: 107..121,
1132 name: "nested_test_11",
1137 "root_tests::nested_tests_0::nested_tests_1::nested_test_11",
1146 use_name_in_title: false,
1147 nav: NavigationTarget {
1151 full_range: 140..182,
1152 focus_range: 163..177,
1153 name: "nested_test_12",
1158 "root_tests::nested_tests_0::nested_tests_1::nested_test_12",
1167 use_name_in_title: false,
1168 nav: NavigationTarget {
1172 full_range: 202..286,
1173 focus_range: 206..220,
1174 name: "nested_tests_2",
1176 description: "mod nested_tests_2",
1179 path: "root_tests::nested_tests_0::nested_tests_2",
1184 use_name_in_title: false,
1185 nav: NavigationTarget {
1189 full_range: 235..276,
1190 focus_range: 258..271,
1191 name: "nested_test_2",
1196 "root_tests::nested_tests_0::nested_tests_2::nested_test_2",
1210 fn test_runnables_with_feature() {
1213 //- /lib.rs crate:foo cfg:feature=foo
1216 #[cfg(feature = "foo")]
1223 use_name_in_title: false,
1224 nav: NavigationTarget {
1238 use_name_in_title: false,
1239 nav: NavigationTarget {
1244 focus_range: 36..45,
1271 fn test_runnables_with_features() {
1274 //- /lib.rs crate:foo cfg:feature=foo,feature=bar
1277 #[cfg(all(feature = "foo", feature = "bar"))]
1284 use_name_in_title: false,
1285 nav: NavigationTarget {
1299 use_name_in_title: false,
1300 nav: NavigationTarget {
1305 focus_range: 58..67,
1342 fn test_runnables_no_test_function_in_module() {
1359 fn test_doc_runnables_impl_mod() {
1377 use_name_in_title: false,
1378 nav: NavigationTarget {
1398 fn test_runnables_in_macro() {
1422 &[TestMod, TestMod, Test, Test, TestMod],
1426 use_name_in_title: false,
1427 nav: NavigationTarget {
1441 use_name_in_title: false,
1442 nav: NavigationTarget {
1446 full_range: 202..227,
1447 focus_range: 206..211,
1450 description: "mod tests",
1458 use_name_in_title: false,
1459 nav: NavigationTarget {
1463 full_range: 218..225,
1478 use_name_in_title: true,
1479 nav: NavigationTarget {
1483 full_range: 228..236,
1489 "tests2::foo_test2",
1498 use_name_in_title: true,
1499 nav: NavigationTarget {
1503 full_range: 228..236,
1506 description: "mod tests2",
1538 &[Test, Test, Test, TestMod],
1542 use_name_in_title: true,
1543 nav: NavigationTarget {
1547 full_range: 210..217,
1562 use_name_in_title: true,
1563 nav: NavigationTarget {
1567 full_range: 210..217,
1582 use_name_in_title: true,
1583 nav: NavigationTarget {
1587 full_range: 210..217,
1602 use_name_in_title: true,
1603 nav: NavigationTarget {
1607 full_range: 210..217,
1610 description: "mod foo_tests",
1623 fn dont_recurse_in_outline_submodules() {
1643 fn outline_submodule1() {
1659 use_name_in_title: false,
1660 nav: NavigationTarget {
1668 description: "mod m",
1681 fn outline_submodule2() {
1693 &[TestMod, Test, Test],
1697 use_name_in_title: false,
1698 nav: NavigationTarget {
1712 use_name_in_title: false,
1713 nav: NavigationTarget {
1718 focus_range: 12..14,
1733 use_name_in_title: false,
1734 nav: NavigationTarget {
1739 focus_range: 31..33,
1759 fn attributed_module() {
1762 //- proc_macros: identity
1765 #[proc_macros::identity]
1773 &[TestMod, Test, Test],
1777 use_name_in_title: true,
1778 nav: NavigationTarget {
1783 focus_range: 30..36,
1786 description: "mod module",
1794 use_name_in_title: true,
1795 nav: NavigationTarget {
1800 focus_range: 58..60,
1815 use_name_in_title: true,
1816 nav: NavigationTarget {
1821 focus_range: 85..87,
1841 fn find_no_tests() {
1854 fn find_direct_fn_test() {
1870 use_name_in_title: false,
1871 nav: NavigationTarget {
1876 focus_range: 46..54,
1896 fn find_direct_struct_test() {
1901 fn foo(arg: &Foo) { };
1915 use_name_in_title: false,
1916 nav: NavigationTarget {
1920 full_range: 71..122,
1921 focus_range: 86..94,
1941 fn find_indirect_fn_test() {
1967 use_name_in_title: false,
1968 nav: NavigationTarget {
1972 full_range: 133..183,
1973 focus_range: 148..156,
1993 fn tests_are_unique() {
2019 use_name_in_title: false,
2020 nav: NavigationTarget {
2024 full_range: 52..115,
2025 focus_range: 67..75,
2040 use_name_in_title: false,
2041 nav: NavigationTarget {
2045 full_range: 121..185,
2046 focus_range: 136..145,
2066 fn doc_test_type_params() {
2075 impl<T, U> Foo<T, U> {
2083 impl Foo<Foo<(), ()>, ()> {
2089 &[DocTest, DocTest, DocTest, DocTest],
2093 use_name_in_title: false,
2094 nav: NavigationTarget {
2098 full_range: 20..103,
2099 focus_range: 47..56,
2111 use_name_in_title: false,
2112 nav: NavigationTarget {
2116 full_range: 63..101,
2127 use_name_in_title: false,
2128 nav: NavigationTarget {
2132 full_range: 105..188,
2133 focus_range: 126..146,
2139 "Foo<Foo<(),()>,()>",
2145 use_name_in_title: false,
2146 nav: NavigationTarget {
2150 full_range: 153..186,
2155 "Foo<Foo<(),()>,()>::t",
2166 fn doc_test_macro_export_mbe() {
2209 use_name_in_title: false,
2210 nav: NavigationTarget {