6 use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, InFile, Semantics};
7 use ide_assists::utils::test_related_attribute;
9 base_db::{FilePosition, FileRange},
10 helpers::visit_file_defs,
12 RootDatabase, SymbolKind,
14 use itertools::Itertools;
15 use rustc_hash::{FxHashMap, FxHashSet};
16 use stdx::{always, format_to};
17 use syntax::ast::{self, AstNode, AttrsOwner};
20 display::{ToNav, TryToNav},
21 references, FileId, NavigationTarget,
24 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
26 pub use_name_in_title: bool,
27 pub nav: NavigationTarget,
28 pub kind: RunnableKind,
29 pub cfg: Option<CfgExpr>,
32 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
38 impl fmt::Display for TestId {
39 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41 TestId::Name(name) => write!(f, "{}", name),
42 TestId::Path(path) => write!(f, "{}", path),
47 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
48 pub enum RunnableKind {
49 Test { test_id: TestId, attr: TestAttr },
50 TestMod { path: String },
51 Bench { test_id: TestId },
52 DocTest { test_id: TestId },
57 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
58 enum RunnableTestKind {
67 // test package::module::testname
68 pub fn label(&self, target: Option<String>) -> String {
70 RunnableKind::Test { test_id, .. } => format!("test {}", test_id),
71 RunnableKind::TestMod { path } => format!("test-mod {}", path),
72 RunnableKind::Bench { test_id } => format!("bench {}", test_id),
73 RunnableKind::DocTest { test_id, .. } => format!("doctest {}", test_id),
74 RunnableKind::Bin => {
75 target.map_or_else(|| "run binary".to_string(), |t| format!("run {}", t))
80 pub fn title(&self) -> String {
81 let mut s = String::from("▶\u{fe0e} Run ");
82 if self.use_name_in_title {
83 format_to!(s, "{}", self.nav.name);
84 if !matches!(self.kind, RunnableKind::Bin) {
88 let suffix = match &self.kind {
89 RunnableKind::TestMod { .. } => "Tests",
90 RunnableKind::Test { .. } => "Test",
91 RunnableKind::DocTest { .. } => "Doctest",
92 RunnableKind::Bench { .. } => "Bench",
93 RunnableKind::Bin => return s,
100 fn test_kind(&self) -> RunnableTestKind {
102 RunnableKind::TestMod { .. } => RunnableTestKind::TestMod,
103 RunnableKind::Test { .. } => RunnableTestKind::Test,
104 RunnableKind::DocTest { .. } => RunnableTestKind::DocTest,
105 RunnableKind::Bench { .. } => RunnableTestKind::Bench,
106 RunnableKind::Bin => RunnableTestKind::Bin,
113 // Shows a popup suggesting to run a test/benchmark/binary **at the current cursor
114 // location**. Super useful for repeatedly running just a single test. Do bind this
118 // | Editor | Action Name
120 // | VS Code | **Rust Analyzer: Run**
122 // image::https://user-images.githubusercontent.com/48062697/113065583-055aae80-91b1-11eb-958f-d67efcaf6a2f.gif[]
123 pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
124 let sema = Semantics::new(db);
126 let mut res = Vec::new();
127 // Record all runnables that come from macro expansions here instead.
128 // In case an expansion creates multiple runnables we want to name them to avoid emitting a bunch of equally named runnables.
129 let mut in_macro_expansion = FxHashMap::<hir::HirFileId, Vec<Runnable>>::default();
130 let mut add_opt = |runnable: Option<Runnable>, def| {
131 if let Some(runnable) = runnable.filter(|runnable| {
133 runnable.nav.file_id == file_id,
134 "tried adding a runnable pointing to a different file: {:?} for {:?}",
139 if let Some(def) = def {
140 let file_id = match def {
141 hir::ModuleDef::Module(it) => it.declaration_source(db).map(|src| src.file_id),
142 hir::ModuleDef::Function(it) => it.source(db).map(|src| src.file_id),
145 if let Some(file_id) = file_id.filter(|file| file.call_node(db).is_some()) {
146 in_macro_expansion.entry(file_id).or_default().push(runnable);
153 visit_file_defs(&sema, file_id, &mut |def| match def {
154 Either::Left(def) => {
155 let runnable = match def {
156 hir::ModuleDef::Module(it) => runnable_mod(&sema, it),
157 hir::ModuleDef::Function(it) => runnable_fn(&sema, it),
160 add_opt(runnable.or_else(|| module_def_doctest(sema.db, def)), Some(def));
162 Either::Right(impl_) => {
163 add_opt(runnable_impl(&sema, &impl_), None);
170 hir::AssocItem::Function(it) => runnable_fn(&sema, it)
171 .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()),
178 .for_each(|(r, assoc)| add_opt(r, Some(assoc.into())));
182 sema.to_module_defs(file_id)
183 .map(|it| runnable_mod_outline_definition(&sema, it))
184 .for_each(|it| add_opt(it, None));
186 res.extend(in_macro_expansion.into_iter().flat_map(|(_, runnables)| {
187 let use_name_in_title = runnables.len() != 1;
188 runnables.into_iter().map(move |mut r| {
189 r.use_name_in_title = use_name_in_title;
196 // Feature: Related Tests
198 // Provides a sneak peek of all tests where the current item is used.
200 // The simplest way to use this feature is via the context menu:
201 // - Right-click on the selected item. The context menu opens.
202 // - Select **Peek related tests**
205 // | Editor | Action Name
207 // | VS Code | **Rust Analyzer: Peek related tests**
209 pub(crate) fn related_tests(
211 position: FilePosition,
212 search_scope: Option<SearchScope>,
214 let sema = Semantics::new(db);
215 let mut res: FxHashSet<Runnable> = FxHashSet::default();
217 find_related_tests(&sema, position, search_scope, &mut res);
219 res.into_iter().collect_vec()
222 fn find_related_tests(
223 sema: &Semantics<RootDatabase>,
224 position: FilePosition,
225 search_scope: Option<SearchScope>,
226 tests: &mut FxHashSet<Runnable>,
228 if let Some(refs) = references::find_all_refs(sema, position, search_scope) {
229 for (file_id, refs) in refs.into_iter().flat_map(|refs| refs.references) {
230 let file = sema.parse(file_id);
231 let file = file.syntax();
233 // create flattened vec of tokens
234 let tokens = refs.iter().flat_map(|(range, _)| {
235 match file.token_at_offset(range.start()).next() {
236 Some(token) => sema.descend_into_macros_many(token),
237 None => Default::default(),
241 // find first suitable ancestor
242 let functions = tokens
243 .filter_map(|token| token.ancestors().find_map(ast::Fn::cast))
244 .map(|f| hir::InFile::new(sema.hir_file_for(f.syntax()), f));
246 for fn_def in functions {
247 // #[test/bench] expands to just the item causing us to lose the attribute, so recover them by going out of the attribute
248 let InFile { value: fn_def, .. } = &fn_def.node_with_attributes(sema.db);
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, fn_def, &module, tests);
260 fn find_related_tests_in_module(
261 sema: &Semantics<RootDatabase>,
263 parent_module: &hir::Module,
264 tests: &mut FxHashSet<Runnable>,
266 if let Some(fn_name) = fn_def.name() {
267 let mod_source = parent_module.definition_source(sema.db);
268 let range = match mod_source.value {
269 hir::ModuleSource::Module(m) => m.syntax().text_range(),
270 hir::ModuleSource::BlockExpr(b) => b.syntax().text_range(),
271 hir::ModuleSource::SourceFile(f) => f.syntax().text_range(),
274 let file_id = mod_source.file_id.original_file(sema.db);
275 let mod_scope = SearchScope::file_range(FileRange { file_id, range });
276 let fn_pos = FilePosition { file_id, offset: fn_name.syntax().text_range().start() };
277 find_related_tests(sema, fn_pos, Some(mod_scope), tests)
281 fn as_test_runnable(sema: &Semantics<RootDatabase>, fn_def: &ast::Fn) -> Option<Runnable> {
282 if test_related_attribute(fn_def).is_some() {
283 let function = sema.to_def(fn_def)?;
284 runnable_fn(sema, function)
290 fn parent_test_module(sema: &Semantics<RootDatabase>, fn_def: &ast::Fn) -> Option<hir::Module> {
291 fn_def.syntax().ancestors().find_map(|node| {
292 let module = ast::Module::cast(node)?;
293 let module = sema.to_def(&module)?;
295 if has_test_function_or_multiple_test_submodules(sema, &module) {
303 pub(crate) fn runnable_fn(sema: &Semantics<RootDatabase>, def: hir::Function) -> Option<Runnable> {
304 // #[test/bench] expands to just the item causing us to lose the attribute, so recover them by going out of the attribute
305 let func = def.source(sema.db)?.node_with_attributes(sema.db);
306 let name_string = def.name(sema.db).to_string();
308 let root = def.module(sema.db).krate().root_module(sema.db);
310 let kind = if name_string == "main" && def.module(sema.db) == root {
313 let canonical_path = {
314 let def: hir::ModuleDef = def.into();
315 def.canonical_path(sema.db)
317 let test_id = canonical_path.map(TestId::Path).unwrap_or(TestId::Name(name_string));
319 if test_related_attribute(&func.value).is_some() {
320 let attr = TestAttr::from_fn(&func.value);
321 RunnableKind::Test { test_id, attr }
322 } else if func.value.has_atom_attr("bench") {
323 RunnableKind::Bench { test_id }
329 let nav = NavigationTarget::from_named(
331 func.as_ref().map(|it| it as &dyn ast::NameOwner),
332 SymbolKind::Function,
334 let cfg = def.attrs(sema.db).cfg();
335 Some(Runnable { use_name_in_title: false, nav, kind, cfg })
338 pub(crate) fn runnable_mod(sema: &Semantics<RootDatabase>, def: hir::Module) -> Option<Runnable> {
339 if !has_test_function_or_multiple_test_submodules(sema, &def) {
343 def.path_to_root(sema.db).into_iter().rev().filter_map(|it| it.name(sema.db)).join("::");
345 let attrs = def.attrs(sema.db);
346 let cfg = attrs.cfg();
347 let nav = NavigationTarget::from_module_to_decl(sema.db, def);
348 Some(Runnable { use_name_in_title: false, nav, kind: RunnableKind::TestMod { path }, cfg })
351 pub(crate) fn runnable_impl(sema: &Semantics<RootDatabase>, def: &hir::Impl) -> Option<Runnable> {
352 let attrs = def.attrs(sema.db);
353 if !has_runnable_doc_test(&attrs) {
356 let cfg = attrs.cfg();
357 let nav = def.try_to_nav(sema.db)?;
358 let ty = def.self_ty(sema.db);
359 let adt_name = ty.as_adt()?.name(sema.db);
360 let mut ty_args = ty.type_arguments().peekable();
361 let params = if ty_args.peek().is_some() {
362 format!("<{}>", ty_args.format_with(", ", |ty, cb| cb(&ty.display(sema.db))))
366 let test_id = TestId::Path(format!("{}{}", adt_name, params));
368 Some(Runnable { use_name_in_title: false, nav, kind: RunnableKind::DocTest { test_id }, cfg })
371 /// Creates a test mod runnable for outline modules at the top of their definition.
372 fn runnable_mod_outline_definition(
373 sema: &Semantics<RootDatabase>,
375 ) -> Option<Runnable> {
376 if !has_test_function_or_multiple_test_submodules(sema, &def) {
380 def.path_to_root(sema.db).into_iter().rev().filter_map(|it| it.name(sema.db)).join("::");
382 let attrs = def.attrs(sema.db);
383 let cfg = attrs.cfg();
384 match def.definition_source(sema.db).value {
385 hir::ModuleSource::SourceFile(_) => Some(Runnable {
386 use_name_in_title: false,
387 nav: def.to_nav(sema.db),
388 kind: RunnableKind::TestMod { path },
395 fn module_def_doctest(db: &RootDatabase, def: hir::ModuleDef) -> Option<Runnable> {
396 let attrs = match def {
397 hir::ModuleDef::Module(it) => it.attrs(db),
398 hir::ModuleDef::Function(it) => it.attrs(db),
399 hir::ModuleDef::Adt(it) => it.attrs(db),
400 hir::ModuleDef::Variant(it) => it.attrs(db),
401 hir::ModuleDef::Const(it) => it.attrs(db),
402 hir::ModuleDef::Static(it) => it.attrs(db),
403 hir::ModuleDef::Trait(it) => it.attrs(db),
404 hir::ModuleDef::TypeAlias(it) => it.attrs(db),
405 hir::ModuleDef::BuiltinType(_) => return None,
407 if !has_runnable_doc_test(&attrs) {
410 let def_name = def.name(db)?;
412 let mut path = String::new();
413 def.canonical_module_path(db)?
414 .flat_map(|it| it.name(db))
415 .for_each(|name| format_to!(path, "{}::", name));
416 // This probably belongs to canonical_path?
417 if let Some(assoc_item) = def.as_assoc_item(db) {
418 if let hir::AssocItemContainer::Impl(imp) = assoc_item.container(db) {
419 let ty = imp.self_ty(db);
420 if let Some(adt) = ty.as_adt() {
421 let name = adt.name(db);
422 let mut ty_args = ty.type_arguments().peekable();
423 format_to!(path, "{}", name);
424 if ty_args.peek().is_some() {
428 ty_args.format_with(", ", |ty, cb| cb(&ty.display(db)))
431 format_to!(path, "::{}", def_name);
436 format_to!(path, "{}", def_name);
440 let test_id = path.map_or_else(|| TestId::Name(def_name.to_string()), TestId::Path);
442 let mut nav = match def {
443 hir::ModuleDef::Module(def) => NavigationTarget::from_module_to_decl(db, def),
444 def => def.try_to_nav(db)?,
446 nav.focus_range = None;
447 nav.description = None;
451 use_name_in_title: false,
453 kind: RunnableKind::DocTest { test_id },
459 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
460 pub struct TestAttr {
465 fn from_fn(fn_def: &ast::Fn) -> TestAttr {
468 .filter_map(|attr| attr.simple_name())
469 .any(|attribute_text| attribute_text == "ignore");
474 const RUSTDOC_FENCE: &str = "```";
475 const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
476 &["", "rust", "should_panic", "edition2015", "edition2018", "edition2021"];
478 fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool {
479 attrs.docs().map_or(false, |doc| {
480 let mut in_code_block = false;
482 for line in String::from(doc).lines() {
483 if let Some(header) = line.strip_prefix(RUSTDOC_FENCE) {
484 in_code_block = !in_code_block;
489 .all(|sub| RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE.contains(&sub.trim()))
500 // We could create runnables for modules with number_of_test_submodules > 0,
501 // but that bloats the runnables for no real benefit, since all tests can be run by the submodule already
502 fn has_test_function_or_multiple_test_submodules(
503 sema: &Semantics<RootDatabase>,
504 module: &hir::Module,
506 let mut number_of_test_submodules = 0;
508 for item in module.declarations(sema.db) {
510 hir::ModuleDef::Function(f) => {
511 if let Some(it) = f.source(sema.db) {
512 // #[test/bench] expands to just the item causing us to lose the attribute, so recover them by going out of the attribute
513 let it = it.node_with_attributes(sema.db);
514 if test_related_attribute(&it.value).is_some() {
519 hir::ModuleDef::Module(submodule) => {
520 if has_test_function_or_multiple_test_submodules(sema, &submodule) {
521 number_of_test_submodules += 1;
528 number_of_test_submodules > 1
533 use expect_test::{expect, Expect};
537 use super::{RunnableTestKind::*, *};
541 // FIXME: fold this into `expect` as well
542 actions: &[RunnableTestKind],
545 let (analysis, position) = fixture::position(ra_fixture);
546 let runnables = analysis.runnables(position.file_id).unwrap();
547 expect.assert_debug_eq(&runnables);
550 runnables.into_iter().map(|it| it.test_kind()).collect::<Vec<_>>().as_slice()
554 fn check_tests(ra_fixture: &str, expect: Expect) {
555 let (analysis, position) = fixture::position(ra_fixture);
556 let tests = analysis.related_tests(position, None).unwrap();
557 expect.assert_debug_eq(&tests);
561 fn test_runnables() {
582 &[Bin, Test, Test, Bench, TestMod],
586 use_name_in_title: false,
587 nav: NavigationTarget {
600 use_name_in_title: false,
601 nav: NavigationTarget {
621 use_name_in_title: false,
622 nav: NavigationTarget {
642 use_name_in_title: false,
643 nav: NavigationTarget {
660 use_name_in_title: false,
661 nav: NavigationTarget {
680 fn test_runnables_doc_test() {
690 fn should_have_runnable() {}
695 fn should_have_runnable_1() {}
704 fn should_have_runnable_2() {}
711 fn should_have_no_runnable_3() {}
718 fn should_have_no_runnable_4() {}
723 fn should_have_no_runnable() {}
728 fn should_have_no_runnable_2() {}
733 fn should_have_no_runnable_3() {}
736 /// arbitrary plain text
738 fn should_have_no_runnable_4() {}
741 /// arbitrary plain text
747 fn should_have_no_runnable_5() {}
752 fn should_have_no_runnable_6() {}
757 struct StructWithRunnable(String);
762 impl StructWithRunnable {}
773 impl Test for StructWithRunnable {}
775 &[Bin, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest, DocTest],
779 use_name_in_title: false,
780 nav: NavigationTarget {
793 use_name_in_title: false,
794 nav: NavigationTarget {
799 name: "should_have_runnable",
803 "should_have_runnable",
809 use_name_in_title: false,
810 nav: NavigationTarget {
815 name: "should_have_runnable_1",
819 "should_have_runnable_1",
825 use_name_in_title: false,
826 nav: NavigationTarget {
830 full_range: 150..254,
831 name: "should_have_runnable_2",
835 "should_have_runnable_2",
841 use_name_in_title: false,
842 nav: NavigationTarget {
846 full_range: 256..320,
847 name: "should_have_no_runnable_3",
851 "should_have_no_runnable_3",
857 use_name_in_title: false,
858 nav: NavigationTarget {
862 full_range: 322..398,
863 name: "should_have_no_runnable_4",
867 "should_have_no_runnable_4",
873 use_name_in_title: false,
874 nav: NavigationTarget {
878 full_range: 900..965,
879 name: "StructWithRunnable",
883 "StructWithRunnable",
889 use_name_in_title: false,
890 nav: NavigationTarget {
894 full_range: 967..1024,
895 focus_range: 1003..1021,
901 "StructWithRunnable",
907 use_name_in_title: false,
908 nav: NavigationTarget {
912 full_range: 1088..1154,
913 focus_range: 1133..1151,
919 "StructWithRunnable",
930 fn test_runnables_doc_test_in_impl() {
949 use_name_in_title: false,
950 nav: NavigationTarget {
963 use_name_in_title: false,
964 nav: NavigationTarget {
984 fn test_runnables_module() {
998 use_name_in_title: false,
999 nav: NavigationTarget {
1007 description: "mod test_mod",
1015 use_name_in_title: false,
1016 nav: NavigationTarget {
1021 focus_range: 35..44,
1027 "test_mod::test_foo1",
1041 fn only_modules_with_test_functions_or_more_than_one_test_submodule_have_runners() {
1047 mod nested_tests_0 {
1048 mod nested_tests_1 {
1050 fn nested_test_11() {}
1053 fn nested_test_12() {}
1056 mod nested_tests_2 {
1058 fn nested_test_2() {}
1061 mod nested_tests_3 {}
1064 mod nested_tests_4 {}
1067 &[TestMod, TestMod, TestMod, Test, Test, Test],
1071 use_name_in_title: false,
1072 nav: NavigationTarget {
1076 full_range: 22..323,
1077 focus_range: 26..40,
1078 name: "nested_tests_0",
1080 description: "mod nested_tests_0",
1083 path: "root_tests::nested_tests_0",
1088 use_name_in_title: false,
1089 nav: NavigationTarget {
1093 full_range: 51..192,
1094 focus_range: 55..69,
1095 name: "nested_tests_1",
1097 description: "mod nested_tests_1",
1100 path: "root_tests::nested_tests_0::nested_tests_1",
1105 use_name_in_title: false,
1106 nav: NavigationTarget {
1110 full_range: 202..286,
1111 focus_range: 206..220,
1112 name: "nested_tests_2",
1114 description: "mod nested_tests_2",
1117 path: "root_tests::nested_tests_0::nested_tests_2",
1122 use_name_in_title: false,
1123 nav: NavigationTarget {
1127 full_range: 84..126,
1128 focus_range: 107..121,
1129 name: "nested_test_11",
1134 "root_tests::nested_tests_0::nested_tests_1::nested_test_11",
1143 use_name_in_title: false,
1144 nav: NavigationTarget {
1148 full_range: 140..182,
1149 focus_range: 163..177,
1150 name: "nested_test_12",
1155 "root_tests::nested_tests_0::nested_tests_1::nested_test_12",
1164 use_name_in_title: false,
1165 nav: NavigationTarget {
1169 full_range: 235..276,
1170 focus_range: 258..271,
1171 name: "nested_test_2",
1176 "root_tests::nested_tests_0::nested_tests_2::nested_test_2",
1190 fn test_runnables_with_feature() {
1193 //- /lib.rs crate:foo cfg:feature=foo
1196 #[cfg(feature = "foo")]
1203 use_name_in_title: false,
1204 nav: NavigationTarget {
1209 focus_range: 36..45,
1231 use_name_in_title: false,
1232 nav: NavigationTarget {
1251 fn test_runnables_with_features() {
1254 //- /lib.rs crate:foo cfg:feature=foo,feature=bar
1257 #[cfg(all(feature = "foo", feature = "bar"))]
1264 use_name_in_title: false,
1265 nav: NavigationTarget {
1270 focus_range: 58..67,
1302 use_name_in_title: false,
1303 nav: NavigationTarget {
1322 fn test_runnables_no_test_function_in_module() {
1339 fn test_doc_runnables_impl_mod() {
1357 use_name_in_title: false,
1358 nav: NavigationTarget {
1378 fn test_runnables_in_macro() {
1402 &[TestMod, TestMod, TestMod, Test, Test],
1406 use_name_in_title: false,
1407 nav: NavigationTarget {
1411 full_range: 202..227,
1412 focus_range: 206..211,
1415 description: "mod tests",
1423 use_name_in_title: false,
1424 nav: NavigationTarget {
1438 use_name_in_title: true,
1439 nav: NavigationTarget {
1443 full_range: 228..236,
1444 focus_range: 228..236,
1447 description: "mod tests2",
1455 use_name_in_title: true,
1456 nav: NavigationTarget {
1460 full_range: 228..236,
1466 "tests2::foo_test2",
1475 use_name_in_title: false,
1476 nav: NavigationTarget {
1480 full_range: 218..225,
1519 &[TestMod, Test, Test, Test],
1523 use_name_in_title: true,
1524 nav: NavigationTarget {
1528 full_range: 210..217,
1529 focus_range: 210..217,
1532 description: "mod foo_tests",
1540 use_name_in_title: true,
1541 nav: NavigationTarget {
1545 full_range: 210..217,
1560 use_name_in_title: true,
1561 nav: NavigationTarget {
1565 full_range: 210..217,
1580 use_name_in_title: true,
1581 nav: NavigationTarget {
1585 full_range: 210..217,
1605 fn dont_recurse_in_outline_submodules() {
1625 fn outline_submodule1() {
1641 use_name_in_title: false,
1642 nav: NavigationTarget {
1650 description: "mod m",
1663 fn outline_submodule2() {
1675 &[Test, Test, TestMod],
1679 use_name_in_title: false,
1680 nav: NavigationTarget {
1685 focus_range: 12..14,
1700 use_name_in_title: false,
1701 nav: NavigationTarget {
1706 focus_range: 31..33,
1721 use_name_in_title: false,
1722 nav: NavigationTarget {
1741 fn attributed_module() {
1744 //- proc_macros: identity
1747 #[proc_macros::identity]
1755 &[TestMod, Test, Test],
1759 use_name_in_title: true,
1760 nav: NavigationTarget {
1765 focus_range: 30..36,
1768 description: "mod module",
1776 use_name_in_title: true,
1777 nav: NavigationTarget {
1782 focus_range: 58..60,
1797 use_name_in_title: true,
1798 nav: NavigationTarget {
1803 focus_range: 85..87,
1823 fn find_no_tests() {
1836 fn find_direct_fn_test() {
1852 use_name_in_title: false,
1853 nav: NavigationTarget {
1858 focus_range: 46..54,
1878 fn find_direct_struct_test() {
1883 fn foo(arg: &Foo) { };
1897 use_name_in_title: false,
1898 nav: NavigationTarget {
1902 full_range: 71..122,
1903 focus_range: 86..94,
1923 fn find_indirect_fn_test() {
1949 use_name_in_title: false,
1950 nav: NavigationTarget {
1954 full_range: 133..183,
1955 focus_range: 148..156,
1975 fn tests_are_unique() {
2001 use_name_in_title: false,
2002 nav: NavigationTarget {
2006 full_range: 52..115,
2007 focus_range: 67..75,
2022 use_name_in_title: false,
2023 nav: NavigationTarget {
2027 full_range: 121..185,
2028 focus_range: 136..145,
2048 fn doc_test_type_params() {
2055 impl<T, U> Foo<T, U> {
2065 use_name_in_title: false,
2066 nav: NavigationTarget {