]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/hover.rs
Merge #6817
[rust.git] / crates / ide / src / hover.rs
1 use hir::{
2     Adt, AsAssocItem, AssocItemContainer, FieldSource, HasAttrs, HasSource, HirDisplay, Module,
3     ModuleDef, ModuleSource, Semantics,
4 };
5 use ide_db::base_db::SourceDatabase;
6 use ide_db::{
7     defs::{Definition, NameClass, NameRefClass},
8     RootDatabase,
9 };
10 use itertools::Itertools;
11 use stdx::format_to;
12 use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};
13 use test_utils::mark;
14
15 use crate::{
16     display::{macro_label, ShortLabel, ToNav, TryToNav},
17     doc_links::{remove_links, rewrite_links},
18     markdown_remove::remove_markdown,
19     markup::Markup,
20     runnables::runnable,
21     FileId, FilePosition, NavigationTarget, RangeInfo, Runnable,
22 };
23
24 #[derive(Clone, Debug, PartialEq, Eq)]
25 pub struct HoverConfig {
26     pub implementations: bool,
27     pub run: bool,
28     pub debug: bool,
29     pub goto_type_def: bool,
30     pub links_in_hover: bool,
31     pub markdown: bool,
32 }
33
34 impl Default for HoverConfig {
35     fn default() -> Self {
36         Self {
37             implementations: true,
38             run: true,
39             debug: true,
40             goto_type_def: true,
41             links_in_hover: true,
42             markdown: true,
43         }
44     }
45 }
46
47 impl HoverConfig {
48     pub const NO_ACTIONS: Self = Self {
49         implementations: false,
50         run: false,
51         debug: false,
52         goto_type_def: false,
53         links_in_hover: true,
54         markdown: true,
55     };
56
57     pub fn any(&self) -> bool {
58         self.implementations || self.runnable() || self.goto_type_def
59     }
60
61     pub fn none(&self) -> bool {
62         !self.any()
63     }
64
65     pub fn runnable(&self) -> bool {
66         self.run || self.debug
67     }
68 }
69
70 #[derive(Debug, Clone)]
71 pub enum HoverAction {
72     Runnable(Runnable),
73     Implementaion(FilePosition),
74     GoToType(Vec<HoverGotoTypeData>),
75 }
76
77 #[derive(Debug, Clone, Eq, PartialEq)]
78 pub struct HoverGotoTypeData {
79     pub mod_path: String,
80     pub nav: NavigationTarget,
81 }
82
83 /// Contains the results when hovering over an item
84 #[derive(Debug, Default)]
85 pub struct HoverResult {
86     pub markup: Markup,
87     pub actions: Vec<HoverAction>,
88 }
89
90 // Feature: Hover
91 //
92 // Shows additional information, like type of an expression or documentation for definition when "focusing" code.
93 // Focusing is usually hovering with a mouse, but can also be triggered with a shortcut.
94 pub(crate) fn hover(
95     db: &RootDatabase,
96     position: FilePosition,
97     links_in_hover: bool,
98     markdown: bool,
99 ) -> Option<RangeInfo<HoverResult>> {
100     let sema = Semantics::new(db);
101     let file = sema.parse(position.file_id).syntax().clone();
102     let token = pick_best(file.token_at_offset(position.offset))?;
103     let token = sema.descend_into_macros(token);
104
105     let mut res = HoverResult::default();
106
107     let node = token.parent();
108     let definition = match_ast! {
109         match node {
110             ast::Name(name) => NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db)),
111             ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
112             _ => None,
113         }
114     };
115     if let Some(definition) = definition {
116         if let Some(markup) = hover_for_definition(db, definition) {
117             let markup = if !markdown {
118                 remove_markdown(&markup.as_str())
119             } else if links_in_hover {
120                 rewrite_links(db, &markup.as_str(), &definition)
121             } else {
122                 remove_links(&markup.as_str())
123             };
124             res.markup = Markup::from(markup);
125             if let Some(action) = show_implementations_action(db, definition) {
126                 res.actions.push(action);
127             }
128
129             if let Some(action) = runnable_action(&sema, definition, position.file_id) {
130                 res.actions.push(action);
131             }
132
133             if let Some(action) = goto_type_action(db, definition) {
134                 res.actions.push(action);
135             }
136
137             let range = sema.original_range(&node).range;
138             return Some(RangeInfo::new(range, res));
139         }
140     }
141
142     if token.kind() == syntax::SyntaxKind::COMMENT {
143         // don't highlight the entire parent node on comment hover
144         return None;
145     }
146
147     let node = token.ancestors().find(|n| {
148         ast::Expr::can_cast(n.kind())
149             || ast::Pat::can_cast(n.kind())
150             || ast::SelfParam::can_cast(n.kind())
151     })?;
152
153     let ty = match_ast! {
154         match node {
155             ast::Expr(it) => sema.type_of_expr(&it)?,
156             ast::Pat(it) => sema.type_of_pat(&it)?,
157             ast::SelfParam(self_param) => sema.type_of_self(&self_param)?,
158             // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve.
159             // (e.g expanding a builtin macro). So we give up here.
160             ast::MacroCall(_it) => return None,
161             _ => return None,
162         }
163     };
164
165     res.markup = if markdown {
166         Markup::fenced_block(&ty.display(db))
167     } else {
168         ty.display(db).to_string().into()
169     };
170     let range = sema.original_range(&node).range;
171     Some(RangeInfo::new(range, res))
172 }
173
174 fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
175     fn to_action(nav_target: NavigationTarget) -> HoverAction {
176         HoverAction::Implementaion(FilePosition {
177             file_id: nav_target.file_id,
178             offset: nav_target.focus_or_full_range().start(),
179         })
180     }
181
182     match def {
183         Definition::ModuleDef(it) => match it {
184             ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.to_nav(db))),
185             ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.to_nav(db))),
186             ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.to_nav(db))),
187             ModuleDef::Trait(it) => Some(to_action(it.to_nav(db))),
188             _ => None,
189         },
190         _ => None,
191     }
192 }
193
194 fn runnable_action(
195     sema: &Semantics<RootDatabase>,
196     def: Definition,
197     file_id: FileId,
198 ) -> Option<HoverAction> {
199     match def {
200         Definition::ModuleDef(it) => match it {
201             ModuleDef::Module(it) => match it.definition_source(sema.db).value {
202                 ModuleSource::Module(it) => runnable(&sema, it.syntax().clone(), file_id)
203                     .map(|it| HoverAction::Runnable(it)),
204                 _ => None,
205             },
206             ModuleDef::Function(it) => {
207                 let src = it.source(sema.db);
208                 if src.file_id != file_id.into() {
209                     mark::hit!(hover_macro_generated_struct_fn_doc_comment);
210                     mark::hit!(hover_macro_generated_struct_fn_doc_attr);
211
212                     return None;
213                 }
214
215                 runnable(&sema, src.value.syntax().clone(), file_id)
216                     .map(|it| HoverAction::Runnable(it))
217             }
218             _ => None,
219         },
220         _ => None,
221     }
222 }
223
224 fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
225     match def {
226         Definition::Local(it) => {
227             let mut targets: Vec<ModuleDef> = Vec::new();
228             let mut push_new_def = |item: ModuleDef| {
229                 if !targets.contains(&item) {
230                     targets.push(item);
231                 }
232             };
233
234             it.ty(db).walk(db, |t| {
235                 if let Some(adt) = t.as_adt() {
236                     push_new_def(adt.into());
237                 } else if let Some(trait_) = t.as_dyn_trait() {
238                     push_new_def(trait_.into());
239                 } else if let Some(traits) = t.as_impl_traits(db) {
240                     traits.into_iter().for_each(|it| push_new_def(it.into()));
241                 } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
242                     push_new_def(trait_.into());
243                 }
244             });
245
246             let targets = targets
247                 .into_iter()
248                 .filter_map(|it| {
249                     Some(HoverGotoTypeData {
250                         mod_path: render_path(
251                             db,
252                             it.module(db)?,
253                             it.name(db).map(|name| name.to_string()),
254                         ),
255                         nav: it.try_to_nav(db)?,
256                     })
257                 })
258                 .collect();
259
260             Some(HoverAction::GoToType(targets))
261         }
262         _ => None,
263     }
264 }
265
266 fn hover_markup(
267     docs: Option<String>,
268     desc: Option<String>,
269     mod_path: Option<String>,
270 ) -> Option<Markup> {
271     match desc {
272         Some(desc) => {
273             let mut buf = String::new();
274
275             if let Some(mod_path) = mod_path {
276                 if !mod_path.is_empty() {
277                     format_to!(buf, "```rust\n{}\n```\n\n", mod_path);
278                 }
279             }
280             format_to!(buf, "```rust\n{}\n```", desc);
281
282             if let Some(doc) = docs {
283                 format_to!(buf, "\n___\n\n{}", doc);
284             }
285             Some(buf.into())
286         }
287         None => docs.map(Markup::from),
288     }
289 }
290
291 fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> {
292     match def {
293         Definition::Field(f) => Some(f.parent_def(db).name(db)),
294         Definition::Local(l) => l.parent(db).name(db),
295         Definition::ModuleDef(md) => match md {
296             ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) {
297                 AssocItemContainer::Trait(t) => Some(t.name(db)),
298                 AssocItemContainer::ImplDef(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)),
299             },
300             ModuleDef::EnumVariant(e) => Some(e.parent_enum(db).name(db)),
301             _ => None,
302         },
303         _ => None,
304     }
305     .map(|name| name.to_string())
306 }
307
308 fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) -> String {
309     let crate_name =
310         db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string());
311     let module_path = module
312         .path_to_root(db)
313         .into_iter()
314         .rev()
315         .flat_map(|it| it.name(db).map(|name| name.to_string()));
316     crate_name.into_iter().chain(module_path).chain(item_name).join("::")
317 }
318
319 fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
320     def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def)))
321 }
322
323 fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
324     let mod_path = definition_mod_path(db, &def);
325     return match def {
326         Definition::Macro(it) => {
327             let label = macro_label(&it.source(db).value);
328             from_def_source_labeled(db, it, Some(label), mod_path)
329         }
330         Definition::Field(def) => {
331             let src = def.source(db).value;
332             if let FieldSource::Named(it) = src {
333                 from_def_source_labeled(db, def, it.short_label(), mod_path)
334             } else {
335                 None
336             }
337         }
338         Definition::ModuleDef(it) => match it {
339             ModuleDef::Module(it) => from_def_source_labeled(
340                 db,
341                 it,
342                 match it.definition_source(db).value {
343                     ModuleSource::Module(it) => it.short_label(),
344                     ModuleSource::SourceFile(it) => it.short_label(),
345                 },
346                 mod_path,
347             ),
348             ModuleDef::Function(it) => from_def_source(db, it, mod_path),
349             ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path),
350             ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path),
351             ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path),
352             ModuleDef::EnumVariant(it) => from_def_source(db, it, mod_path),
353             ModuleDef::Const(it) => from_def_source(db, it, mod_path),
354             ModuleDef::Static(it) => from_def_source(db, it, mod_path),
355             ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
356             ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
357             ModuleDef::BuiltinType(it) => return Some(it.to_string().into()),
358         },
359         Definition::Local(it) => return Some(Markup::fenced_block(&it.ty(db).display(db))),
360         Definition::SelfType(impl_def) => {
361             impl_def.target_ty(db).as_adt().and_then(|adt| match adt {
362                 Adt::Struct(it) => from_def_source(db, it, mod_path),
363                 Adt::Union(it) => from_def_source(db, it, mod_path),
364                 Adt::Enum(it) => from_def_source(db, it, mod_path),
365             })
366         }
367         Definition::TypeParam(_) => {
368             // FIXME: Hover for generic param
369             None
370         }
371     };
372
373     fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup>
374     where
375         D: HasSource<Ast = A> + HasAttrs + Copy,
376         A: ShortLabel,
377     {
378         let short_label = def.source(db).value.short_label();
379         from_def_source_labeled(db, def, short_label, mod_path)
380     }
381
382     fn from_def_source_labeled<D>(
383         db: &RootDatabase,
384         def: D,
385         short_label: Option<String>,
386         mod_path: Option<String>,
387     ) -> Option<Markup>
388     where
389         D: HasAttrs,
390     {
391         let docs = def.attrs(db).docs().map(Into::into);
392         hover_markup(docs, short_label, mod_path)
393     }
394 }
395
396 fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
397     return tokens.max_by_key(priority);
398     fn priority(n: &SyntaxToken) -> usize {
399         match n.kind() {
400             IDENT | INT_NUMBER => 3,
401             T!['('] | T![')'] => 2,
402             kind if kind.is_trivia() => 0,
403             _ => 1,
404         }
405     }
406 }
407
408 #[cfg(test)]
409 mod tests {
410     use expect_test::{expect, Expect};
411     use ide_db::base_db::FileLoader;
412
413     use crate::fixture;
414
415     use super::*;
416
417     fn check_hover_no_result(ra_fixture: &str) {
418         let (analysis, position) = fixture::position(ra_fixture);
419         assert!(analysis.hover(position, true, true).unwrap().is_none());
420     }
421
422     fn check(ra_fixture: &str, expect: Expect) {
423         let (analysis, position) = fixture::position(ra_fixture);
424         let hover = analysis.hover(position, true, true).unwrap().unwrap();
425
426         let content = analysis.db.file_text(position.file_id);
427         let hovered_element = &content[hover.range];
428
429         let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
430         expect.assert_eq(&actual)
431     }
432
433     fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
434         let (analysis, position) = fixture::position(ra_fixture);
435         let hover = analysis.hover(position, false, true).unwrap().unwrap();
436
437         let content = analysis.db.file_text(position.file_id);
438         let hovered_element = &content[hover.range];
439
440         let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
441         expect.assert_eq(&actual)
442     }
443
444     fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) {
445         let (analysis, position) = fixture::position(ra_fixture);
446         let hover = analysis.hover(position, true, false).unwrap().unwrap();
447
448         let content = analysis.db.file_text(position.file_id);
449         let hovered_element = &content[hover.range];
450
451         let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
452         expect.assert_eq(&actual)
453     }
454
455     fn check_actions(ra_fixture: &str, expect: Expect) {
456         let (analysis, position) = fixture::position(ra_fixture);
457         let hover = analysis.hover(position, true, true).unwrap().unwrap();
458         expect.assert_debug_eq(&hover.info.actions)
459     }
460
461     #[test]
462     fn hover_shows_type_of_an_expression() {
463         check(
464             r#"
465 pub fn foo() -> u32 { 1 }
466
467 fn main() {
468     let foo_test = foo()<|>;
469 }
470 "#,
471             expect![[r#"
472                 *foo()*
473                 ```rust
474                 u32
475                 ```
476             "#]],
477         );
478     }
479
480     #[test]
481     fn hover_remove_markdown_if_configured() {
482         check_hover_no_markdown(
483             r#"
484 pub fn foo() -> u32 { 1 }
485
486 fn main() {
487     let foo_test = foo()<|>;
488 }
489 "#,
490             expect![[r#"
491                 *foo()*
492                 u32
493             "#]],
494         );
495     }
496
497     #[test]
498     fn hover_shows_long_type_of_an_expression() {
499         check(
500             r#"
501 struct Scan<A, B, C> { a: A, b: B, c: C }
502 struct Iter<I> { inner: I }
503 enum Option<T> { Some(T), None }
504
505 struct OtherStruct<T> { i: T }
506
507 fn scan<A, B, C>(a: A, b: B, c: C) -> Iter<Scan<OtherStruct<A>, B, C>> {
508     Iter { inner: Scan { a, b, c } }
509 }
510
511 fn main() {
512     let num: i32 = 55;
513     let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> Option<u32> {
514         Option::Some(*memo + value)
515     };
516     let number = 5u32;
517     let mut iter<|> = scan(OtherStruct { i: num }, closure, number);
518 }
519 "#,
520             expect![[r#"
521                 *iter*
522
523                 ```rust
524                 Iter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> Option<u32>, u32>>
525                 ```
526             "#]],
527         );
528     }
529
530     #[test]
531     fn hover_shows_fn_signature() {
532         // Single file with result
533         check(
534             r#"
535 pub fn foo() -> u32 { 1 }
536
537 fn main() { let foo_test = fo<|>o(); }
538 "#,
539             expect![[r#"
540                 *foo*
541
542                 ```rust
543                 test
544                 ```
545
546                 ```rust
547                 pub fn foo() -> u32
548                 ```
549             "#]],
550         );
551
552         // Multiple candidates but results are ambiguous.
553         check(
554             r#"
555 //- /a.rs
556 pub fn foo() -> u32 { 1 }
557
558 //- /b.rs
559 pub fn foo() -> &str { "" }
560
561 //- /c.rs
562 pub fn foo(a: u32, b: u32) {}
563
564 //- /main.rs
565 mod a;
566 mod b;
567 mod c;
568
569 fn main() { let foo_test = fo<|>o(); }
570         "#,
571             expect![[r#"
572                 *foo*
573                 ```rust
574                 {unknown}
575                 ```
576             "#]],
577         );
578     }
579
580     #[test]
581     fn hover_shows_fn_signature_with_type_params() {
582         check(
583             r#"
584 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { }
585
586 fn main() { let foo_test = fo<|>o(); }
587         "#,
588             expect![[r#"
589                 *foo*
590
591                 ```rust
592                 test
593                 ```
594
595                 ```rust
596                 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str
597                 ```
598             "#]],
599         );
600     }
601
602     #[test]
603     fn hover_shows_fn_signature_on_fn_name() {
604         check(
605             r#"
606 pub fn foo<|>(a: u32, b: u32) -> u32 {}
607
608 fn main() { }
609 "#,
610             expect![[r#"
611                 *foo*
612
613                 ```rust
614                 test
615                 ```
616
617                 ```rust
618                 pub fn foo(a: u32, b: u32) -> u32
619                 ```
620             "#]],
621         );
622     }
623
624     #[test]
625     fn hover_shows_fn_doc() {
626         check(
627             r#"
628 /// # Example
629 /// ```
630 /// # use std::path::Path;
631 /// #
632 /// foo(Path::new("hello, world!"))
633 /// ```
634 pub fn foo<|>(_: &Path) {}
635
636 fn main() { }
637 "#,
638             expect![[r##"
639                 *foo*
640
641                 ```rust
642                 test
643                 ```
644
645                 ```rust
646                 pub fn foo(_: &Path)
647                 ```
648
649                 ---
650
651                 # Example
652
653                 ```
654                 # use std::path::Path;
655                 #
656                 foo(Path::new("hello, world!"))
657                 ```
658             "##]],
659         );
660     }
661
662     #[test]
663     fn hover_shows_fn_doc_attr_raw_string() {
664         check(
665             r##"
666 #[doc = r#"Raw string doc attr"#]
667 pub fn foo<|>(_: &Path) {}
668
669 fn main() { }
670 "##,
671             expect![[r##"
672                 *foo*
673
674                 ```rust
675                 test
676                 ```
677
678                 ```rust
679                 pub fn foo(_: &Path)
680                 ```
681
682                 ---
683
684                 Raw string doc attr
685             "##]],
686         );
687     }
688
689     #[test]
690     fn hover_shows_struct_field_info() {
691         // Hovering over the field when instantiating
692         check(
693             r#"
694 struct Foo { field_a: u32 }
695
696 fn main() {
697     let foo = Foo { field_a<|>: 0, };
698 }
699 "#,
700             expect![[r#"
701                 *field_a*
702
703                 ```rust
704                 test::Foo
705                 ```
706
707                 ```rust
708                 field_a: u32
709                 ```
710             "#]],
711         );
712
713         // Hovering over the field in the definition
714         check(
715             r#"
716 struct Foo { field_a<|>: u32 }
717
718 fn main() {
719     let foo = Foo { field_a: 0 };
720 }
721 "#,
722             expect![[r#"
723                 *field_a*
724
725                 ```rust
726                 test::Foo
727                 ```
728
729                 ```rust
730                 field_a: u32
731                 ```
732             "#]],
733         );
734     }
735
736     #[test]
737     fn hover_const_static() {
738         check(
739             r#"const foo<|>: u32 = 123;"#,
740             expect![[r#"
741                 *foo*
742
743                 ```rust
744                 test
745                 ```
746
747                 ```rust
748                 const foo: u32 = 123
749                 ```
750             "#]],
751         );
752         check(
753             r#"static foo<|>: u32 = 456;"#,
754             expect![[r#"
755                 *foo*
756
757                 ```rust
758                 test
759                 ```
760
761                 ```rust
762                 static foo: u32
763                 ```
764             "#]],
765         );
766     }
767
768     #[test]
769     fn hover_default_generic_types() {
770         check(
771             r#"
772 struct Test<K, T = u8> { k: K, t: T }
773
774 fn main() {
775     let zz<|> = Test { t: 23u8, k: 33 };
776 }"#,
777             expect![[r#"
778                 *zz*
779
780                 ```rust
781                 Test<i32, u8>
782                 ```
783             "#]],
784         );
785     }
786
787     #[test]
788     fn hover_some() {
789         check(
790             r#"
791 enum Option<T> { Some(T) }
792 use Option::Some;
793
794 fn main() { So<|>me(12); }
795 "#,
796             expect![[r#"
797                 *Some*
798
799                 ```rust
800                 test::Option
801                 ```
802
803                 ```rust
804                 Some
805                 ```
806             "#]],
807         );
808
809         check(
810             r#"
811 enum Option<T> { Some(T) }
812 use Option::Some;
813
814 fn main() { let b<|>ar = Some(12); }
815 "#,
816             expect![[r#"
817                 *bar*
818
819                 ```rust
820                 Option<i32>
821                 ```
822             "#]],
823         );
824     }
825
826     #[test]
827     fn hover_enum_variant() {
828         check(
829             r#"
830 enum Option<T> {
831     /// The None variant
832     Non<|>e
833 }
834 "#,
835             expect![[r#"
836                 *None*
837
838                 ```rust
839                 test::Option
840                 ```
841
842                 ```rust
843                 None
844                 ```
845
846                 ---
847
848                 The None variant
849             "#]],
850         );
851
852         check(
853             r#"
854 enum Option<T> {
855     /// The Some variant
856     Some(T)
857 }
858 fn main() {
859     let s = Option::Som<|>e(12);
860 }
861 "#,
862             expect![[r#"
863                 *Some*
864
865                 ```rust
866                 test::Option
867                 ```
868
869                 ```rust
870                 Some
871                 ```
872
873                 ---
874
875                 The Some variant
876             "#]],
877         );
878     }
879
880     #[test]
881     fn hover_for_local_variable() {
882         check(
883             r#"fn func(foo: i32) { fo<|>o; }"#,
884             expect![[r#"
885                 *foo*
886
887                 ```rust
888                 i32
889                 ```
890             "#]],
891         )
892     }
893
894     #[test]
895     fn hover_for_local_variable_pat() {
896         check(
897             r#"fn func(fo<|>o: i32) {}"#,
898             expect![[r#"
899                 *foo*
900
901                 ```rust
902                 i32
903                 ```
904             "#]],
905         )
906     }
907
908     #[test]
909     fn hover_local_var_edge() {
910         check(
911             r#"fn func(foo: i32) { if true { <|>foo; }; }"#,
912             expect![[r#"
913                 *foo*
914
915                 ```rust
916                 i32
917                 ```
918             "#]],
919         )
920     }
921
922     #[test]
923     fn hover_for_param_edge() {
924         check(
925             r#"fn func(<|>foo: i32) {}"#,
926             expect![[r#"
927                 *foo*
928
929                 ```rust
930                 i32
931                 ```
932             "#]],
933         )
934     }
935
936     #[test]
937     fn hover_for_param_with_multiple_traits() {
938         check(
939             r#"trait Deref {
940                 type Target: ?Sized;
941             }
942             trait DerefMut {
943                 type Target: ?Sized;
944             }
945             fn f(_x<|>: impl Deref<Target=u8> + DerefMut<Target=u8>) {}"#,
946             expect![[r#"
947                 *_x*
948
949                 ```rust
950                 impl Deref<Target = u8> + DerefMut<Target = u8>
951                 ```
952             "#]],
953         )
954     }
955
956     #[test]
957     fn test_hover_infer_associated_method_result() {
958         check(
959             r#"
960 struct Thing { x: u32 }
961
962 impl Thing {
963     fn new() -> Thing { Thing { x: 0 } }
964 }
965
966 fn main() { let foo_<|>test = Thing::new(); }
967             "#,
968             expect![[r#"
969                 *foo_test*
970
971                 ```rust
972                 Thing
973                 ```
974             "#]],
975         )
976     }
977
978     #[test]
979     fn test_hover_infer_associated_method_exact() {
980         check(
981             r#"
982 mod wrapper {
983     struct Thing { x: u32 }
984
985     impl Thing {
986         fn new() -> Thing { Thing { x: 0 } }
987     }
988 }
989
990 fn main() { let foo_test = wrapper::Thing::new<|>(); }
991 "#,
992             expect![[r#"
993                 *new*
994
995                 ```rust
996                 test::wrapper::Thing
997                 ```
998
999                 ```rust
1000                 fn new() -> Thing
1001                 ```
1002             "#]],
1003         )
1004     }
1005
1006     #[test]
1007     fn test_hover_infer_associated_const_in_pattern() {
1008         check(
1009             r#"
1010 struct X;
1011 impl X {
1012     const C: u32 = 1;
1013 }
1014
1015 fn main() {
1016     match 1 {
1017         X::C<|> => {},
1018         2 => {},
1019         _ => {}
1020     };
1021 }
1022 "#,
1023             expect![[r#"
1024                 *C*
1025
1026                 ```rust
1027                 test
1028                 ```
1029
1030                 ```rust
1031                 const C: u32 = 1
1032                 ```
1033             "#]],
1034         )
1035     }
1036
1037     #[test]
1038     fn test_hover_self() {
1039         check(
1040             r#"
1041 struct Thing { x: u32 }
1042 impl Thing {
1043     fn new() -> Self { Self<|> { x: 0 } }
1044 }
1045 "#,
1046             expect![[r#"
1047                 *Self*
1048
1049                 ```rust
1050                 test
1051                 ```
1052
1053                 ```rust
1054                 struct Thing
1055                 ```
1056             "#]],
1057         );
1058         check(
1059             r#"
1060 struct Thing { x: u32 }
1061 impl Thing {
1062     fn new() -> Self<|> { Self { x: 0 } }
1063 }
1064 "#,
1065             expect![[r#"
1066                 *Self*
1067
1068                 ```rust
1069                 test
1070                 ```
1071
1072                 ```rust
1073                 struct Thing
1074                 ```
1075             "#]],
1076         );
1077         check(
1078             r#"
1079 enum Thing { A }
1080 impl Thing {
1081     pub fn new() -> Self<|> { Thing::A }
1082 }
1083 "#,
1084             expect![[r#"
1085                 *Self*
1086
1087                 ```rust
1088                 test
1089                 ```
1090
1091                 ```rust
1092                 enum Thing
1093                 ```
1094             "#]],
1095         );
1096         check(
1097             r#"
1098         enum Thing { A }
1099         impl Thing {
1100             pub fn thing(a: Self<|>) {}
1101         }
1102         "#,
1103             expect![[r#"
1104                 *Self*
1105
1106                 ```rust
1107                 test
1108                 ```
1109
1110                 ```rust
1111                 enum Thing
1112                 ```
1113             "#]],
1114         );
1115     }
1116
1117     #[test]
1118     fn test_hover_shadowing_pat() {
1119         check(
1120             r#"
1121 fn x() {}
1122
1123 fn y() {
1124     let x = 0i32;
1125     x<|>;
1126 }
1127 "#,
1128             expect![[r#"
1129                 *x*
1130
1131                 ```rust
1132                 i32
1133                 ```
1134             "#]],
1135         )
1136     }
1137
1138     #[test]
1139     fn test_hover_macro_invocation() {
1140         check(
1141             r#"
1142 macro_rules! foo { () => {} }
1143
1144 fn f() { fo<|>o!(); }
1145 "#,
1146             expect![[r#"
1147                 *foo*
1148
1149                 ```rust
1150                 test
1151                 ```
1152
1153                 ```rust
1154                 macro_rules! foo
1155                 ```
1156             "#]],
1157         )
1158     }
1159
1160     #[test]
1161     fn test_hover_tuple_field() {
1162         check(
1163             r#"struct TS(String, i32<|>);"#,
1164             expect![[r#"
1165                 *i32*
1166                 i32
1167             "#]],
1168         )
1169     }
1170
1171     #[test]
1172     fn test_hover_through_macro() {
1173         check(
1174             r#"
1175 macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1176 fn foo() {}
1177 id! {
1178     fn bar() { fo<|>o(); }
1179 }
1180 "#,
1181             expect![[r#"
1182                 *foo*
1183
1184                 ```rust
1185                 test
1186                 ```
1187
1188                 ```rust
1189                 fn foo()
1190                 ```
1191             "#]],
1192         );
1193     }
1194
1195     #[test]
1196     fn test_hover_through_expr_in_macro() {
1197         check(
1198             r#"
1199 macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1200 fn foo(bar:u32) { let a = id!(ba<|>r); }
1201 "#,
1202             expect![[r#"
1203                 *bar*
1204
1205                 ```rust
1206                 u32
1207                 ```
1208             "#]],
1209         );
1210     }
1211
1212     #[test]
1213     fn test_hover_through_expr_in_macro_recursive() {
1214         check(
1215             r#"
1216 macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
1217 macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
1218 fn foo(bar:u32) { let a = id!(ba<|>r); }
1219 "#,
1220             expect![[r#"
1221                 *bar*
1222
1223                 ```rust
1224                 u32
1225                 ```
1226             "#]],
1227         );
1228     }
1229
1230     #[test]
1231     fn test_hover_through_func_in_macro_recursive() {
1232         check(
1233             r#"
1234 macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
1235 macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
1236 fn bar() -> u32 { 0 }
1237 fn foo() { let a = id!([0u32, bar(<|>)] ); }
1238 "#,
1239             expect![[r#"
1240                 *bar()*
1241                 ```rust
1242                 u32
1243                 ```
1244             "#]],
1245         );
1246     }
1247
1248     #[test]
1249     fn test_hover_through_literal_string_in_macro() {
1250         check(
1251             r#"
1252 macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } }
1253 fn foo() {
1254     let mastered_for_itunes = "";
1255     let _ = arr!("Tr<|>acks", &mastered_for_itunes);
1256 }
1257 "#,
1258             expect![[r#"
1259                 *"Tracks"*
1260                 ```rust
1261                 &str
1262                 ```
1263             "#]],
1264         );
1265     }
1266
1267     #[test]
1268     fn test_hover_through_assert_macro() {
1269         check(
1270             r#"
1271 #[rustc_builtin_macro]
1272 macro_rules! assert {}
1273
1274 fn bar() -> bool { true }
1275 fn foo() {
1276     assert!(ba<|>r());
1277 }
1278 "#,
1279             expect![[r#"
1280                 *bar*
1281
1282                 ```rust
1283                 test
1284                 ```
1285
1286                 ```rust
1287                 fn bar() -> bool
1288                 ```
1289             "#]],
1290         );
1291     }
1292
1293     #[test]
1294     fn test_hover_through_literal_string_in_builtin_macro() {
1295         check_hover_no_result(
1296             r#"
1297             #[rustc_builtin_macro]
1298             macro_rules! format {}
1299
1300             fn foo() {
1301                 format!("hel<|>lo {}", 0);
1302             }
1303             "#,
1304         );
1305     }
1306
1307     #[test]
1308     fn test_hover_non_ascii_space_doc() {
1309         check(
1310             "
1311 /// <- `\u{3000}` here
1312 fn foo() { }
1313
1314 fn bar() { fo<|>o(); }
1315 ",
1316             expect![[r#"
1317                 *foo*
1318
1319                 ```rust
1320                 test
1321                 ```
1322
1323                 ```rust
1324                 fn foo()
1325                 ```
1326
1327                 ---
1328
1329                 \<- ` ` here
1330             "#]],
1331         );
1332     }
1333
1334     #[test]
1335     fn test_hover_function_show_qualifiers() {
1336         check(
1337             r#"async fn foo<|>() {}"#,
1338             expect![[r#"
1339                 *foo*
1340
1341                 ```rust
1342                 test
1343                 ```
1344
1345                 ```rust
1346                 async fn foo()
1347                 ```
1348             "#]],
1349         );
1350         check(
1351             r#"pub const unsafe fn foo<|>() {}"#,
1352             expect![[r#"
1353                 *foo*
1354
1355                 ```rust
1356                 test
1357                 ```
1358
1359                 ```rust
1360                 pub const unsafe fn foo()
1361                 ```
1362             "#]],
1363         );
1364         check(
1365             r#"pub(crate) async unsafe extern "C" fn foo<|>() {}"#,
1366             expect![[r#"
1367                 *foo*
1368
1369                 ```rust
1370                 test
1371                 ```
1372
1373                 ```rust
1374                 pub(crate) async unsafe extern "C" fn foo()
1375                 ```
1376             "#]],
1377         );
1378     }
1379
1380     #[test]
1381     fn test_hover_trait_show_qualifiers() {
1382         check_actions(
1383             r"unsafe trait foo<|>() {}",
1384             expect![[r#"
1385                 [
1386                     Implementaion(
1387                         FilePosition {
1388                             file_id: FileId(
1389                                 0,
1390                             ),
1391                             offset: 13,
1392                         },
1393                     ),
1394                 ]
1395             "#]],
1396         );
1397     }
1398
1399     #[test]
1400     fn test_hover_extern_crate() {
1401         check(
1402             r#"
1403 //- /main.rs crate:main deps:std
1404 extern crate st<|>d;
1405 //- /std/lib.rs crate:std
1406 //! Standard library for this test
1407 //!
1408 //! Printed?
1409 //! abc123
1410             "#,
1411             expect![[r#"
1412             *std*
1413             Standard library for this test
1414
1415             Printed?
1416             abc123
1417             "#]],
1418         );
1419         check(
1420             r#"
1421 //- /main.rs crate:main deps:std
1422 extern crate std as ab<|>c;
1423 //- /std/lib.rs crate:std
1424 //! Standard library for this test
1425 //!
1426 //! Printed?
1427 //! abc123
1428             "#,
1429             expect![[r#"
1430             *abc*
1431             Standard library for this test
1432
1433             Printed?
1434             abc123
1435             "#]],
1436         );
1437     }
1438
1439     #[test]
1440     fn test_hover_mod_with_same_name_as_function() {
1441         check(
1442             r#"
1443 use self::m<|>y::Bar;
1444 mod my { pub struct Bar; }
1445
1446 fn my() {}
1447 "#,
1448             expect![[r#"
1449                 *my*
1450
1451                 ```rust
1452                 test
1453                 ```
1454
1455                 ```rust
1456                 mod my
1457                 ```
1458             "#]],
1459         );
1460     }
1461
1462     #[test]
1463     fn test_hover_struct_doc_comment() {
1464         check(
1465             r#"
1466 /// bar docs
1467 struct Bar;
1468
1469 fn foo() { let bar = Ba<|>r; }
1470 "#,
1471             expect![[r#"
1472                 *Bar*
1473
1474                 ```rust
1475                 test
1476                 ```
1477
1478                 ```rust
1479                 struct Bar
1480                 ```
1481
1482                 ---
1483
1484                 bar docs
1485             "#]],
1486         );
1487     }
1488
1489     #[test]
1490     fn test_hover_struct_doc_attr() {
1491         check(
1492             r#"
1493 #[doc = "bar docs"]
1494 struct Bar;
1495
1496 fn foo() { let bar = Ba<|>r; }
1497 "#,
1498             expect![[r#"
1499                 *Bar*
1500
1501                 ```rust
1502                 test
1503                 ```
1504
1505                 ```rust
1506                 struct Bar
1507                 ```
1508
1509                 ---
1510
1511                 bar docs
1512             "#]],
1513         );
1514     }
1515
1516     #[test]
1517     fn test_hover_struct_doc_attr_multiple_and_mixed() {
1518         check(
1519             r#"
1520 /// bar docs 0
1521 #[doc = "bar docs 1"]
1522 #[doc = "bar docs 2"]
1523 struct Bar;
1524
1525 fn foo() { let bar = Ba<|>r; }
1526 "#,
1527             expect![[r#"
1528                 *Bar*
1529
1530                 ```rust
1531                 test
1532                 ```
1533
1534                 ```rust
1535                 struct Bar
1536                 ```
1537
1538                 ---
1539
1540                 bar docs 0
1541                 bar docs 1
1542                 bar docs 2
1543             "#]],
1544         );
1545     }
1546
1547     #[test]
1548     fn test_hover_path_link() {
1549         check(
1550             r#"
1551 pub struct Foo;
1552 /// [Foo](struct.Foo.html)
1553 pub struct B<|>ar
1554 "#,
1555             expect![[r#"
1556                 *Bar*
1557
1558                 ```rust
1559                 test
1560                 ```
1561
1562                 ```rust
1563                 pub struct Bar
1564                 ```
1565
1566                 ---
1567
1568                 [Foo](https://docs.rs/test/*/test/struct.Foo.html)
1569             "#]],
1570         );
1571     }
1572
1573     #[test]
1574     fn test_hover_path_link_no_strip() {
1575         check(
1576             r#"
1577 pub struct Foo;
1578 /// [struct Foo](struct.Foo.html)
1579 pub struct B<|>ar
1580 "#,
1581             expect![[r#"
1582                 *Bar*
1583
1584                 ```rust
1585                 test
1586                 ```
1587
1588                 ```rust
1589                 pub struct Bar
1590                 ```
1591
1592                 ---
1593
1594                 [struct Foo](https://docs.rs/test/*/test/struct.Foo.html)
1595             "#]],
1596         );
1597     }
1598
1599     #[ignore = "path based links currently only support documentation on ModuleDef items"]
1600     #[test]
1601     fn test_hover_path_link_field() {
1602         check(
1603             r#"
1604 pub struct Foo;
1605 pub struct Bar {
1606     /// [Foo](struct.Foo.html)
1607     fie<|>ld: ()
1608 }
1609 "#,
1610             expect![[r#"
1611                 *field*
1612
1613                 ```rust
1614                 test::Bar
1615                 ```
1616
1617                 ```rust
1618                 field: ()
1619                 ```
1620
1621                 ---
1622
1623                 [Foo](https://docs.rs/test/*/test/struct.Foo.html)
1624             "#]],
1625         );
1626     }
1627
1628     #[test]
1629     fn test_hover_intra_link() {
1630         check(
1631             r#"
1632 pub mod foo {
1633     pub struct Foo;
1634 }
1635 /// [Foo](foo::Foo)
1636 pub struct B<|>ar
1637 "#,
1638             expect![[r#"
1639                 *Bar*
1640
1641                 ```rust
1642                 test
1643                 ```
1644
1645                 ```rust
1646                 pub struct Bar
1647                 ```
1648
1649                 ---
1650
1651                 [Foo](https://docs.rs/test/*/test/foo/struct.Foo.html)
1652             "#]],
1653         );
1654     }
1655
1656     #[test]
1657     fn test_hover_intra_link_html_root_url() {
1658         check(
1659             r#"
1660 #![doc(arbitrary_attribute = "test", html_root_url = "https:/example.com", arbitrary_attribute2)]
1661
1662 pub mod foo {
1663     pub struct Foo;
1664 }
1665 /// [Foo](foo::Foo)
1666 pub struct B<|>ar
1667 "#,
1668             expect![[r#"
1669                 *Bar*
1670
1671                 ```rust
1672                 test
1673                 ```
1674
1675                 ```rust
1676                 pub struct Bar
1677                 ```
1678
1679                 ---
1680
1681                 [Foo](https://example.com/test/foo/struct.Foo.html)
1682             "#]],
1683         );
1684     }
1685
1686     #[test]
1687     fn test_hover_intra_link_shortlink() {
1688         check(
1689             r#"
1690 pub struct Foo;
1691 /// [Foo]
1692 pub struct B<|>ar
1693 "#,
1694             expect![[r#"
1695                 *Bar*
1696
1697                 ```rust
1698                 test
1699                 ```
1700
1701                 ```rust
1702                 pub struct Bar
1703                 ```
1704
1705                 ---
1706
1707                 [Foo](https://docs.rs/test/*/test/struct.Foo.html)
1708             "#]],
1709         );
1710     }
1711
1712     #[test]
1713     fn test_hover_intra_link_shortlink_code() {
1714         check(
1715             r#"
1716 pub struct Foo;
1717 /// [`Foo`]
1718 pub struct B<|>ar
1719 "#,
1720             expect![[r#"
1721                 *Bar*
1722
1723                 ```rust
1724                 test
1725                 ```
1726
1727                 ```rust
1728                 pub struct Bar
1729                 ```
1730
1731                 ---
1732
1733                 [`Foo`](https://docs.rs/test/*/test/struct.Foo.html)
1734             "#]],
1735         );
1736     }
1737
1738     #[test]
1739     fn test_hover_intra_link_namespaced() {
1740         check(
1741             r#"
1742 pub struct Foo;
1743 fn Foo() {}
1744 /// [Foo()]
1745 pub struct B<|>ar
1746 "#,
1747             expect![[r#"
1748                 *Bar*
1749
1750                 ```rust
1751                 test
1752                 ```
1753
1754                 ```rust
1755                 pub struct Bar
1756                 ```
1757
1758                 ---
1759
1760                 [Foo](https://docs.rs/test/*/test/struct.Foo.html)
1761             "#]],
1762         );
1763     }
1764
1765     #[test]
1766     fn test_hover_intra_link_shortlink_namspaced_code() {
1767         check(
1768             r#"
1769 pub struct Foo;
1770 /// [`struct Foo`]
1771 pub struct B<|>ar
1772 "#,
1773             expect![[r#"
1774                 *Bar*
1775
1776                 ```rust
1777                 test
1778                 ```
1779
1780                 ```rust
1781                 pub struct Bar
1782                 ```
1783
1784                 ---
1785
1786                 [`Foo`](https://docs.rs/test/*/test/struct.Foo.html)
1787             "#]],
1788         );
1789     }
1790
1791     #[test]
1792     fn test_hover_intra_link_shortlink_namspaced_code_with_at() {
1793         check(
1794             r#"
1795 pub struct Foo;
1796 /// [`struct@Foo`]
1797 pub struct B<|>ar
1798 "#,
1799             expect![[r#"
1800                 *Bar*
1801
1802                 ```rust
1803                 test
1804                 ```
1805
1806                 ```rust
1807                 pub struct Bar
1808                 ```
1809
1810                 ---
1811
1812                 [`Foo`](https://docs.rs/test/*/test/struct.Foo.html)
1813             "#]],
1814         );
1815     }
1816
1817     #[test]
1818     fn test_hover_intra_link_reference() {
1819         check(
1820             r#"
1821 pub struct Foo;
1822 /// [my Foo][foo]
1823 ///
1824 /// [foo]: Foo
1825 pub struct B<|>ar
1826 "#,
1827             expect![[r#"
1828                 *Bar*
1829
1830                 ```rust
1831                 test
1832                 ```
1833
1834                 ```rust
1835                 pub struct Bar
1836                 ```
1837
1838                 ---
1839
1840                 [my Foo](https://docs.rs/test/*/test/struct.Foo.html)
1841             "#]],
1842         );
1843     }
1844
1845     #[test]
1846     fn test_hover_external_url() {
1847         check(
1848             r#"
1849 pub struct Foo;
1850 /// [external](https://www.google.com)
1851 pub struct B<|>ar
1852 "#,
1853             expect![[r#"
1854                 *Bar*
1855
1856                 ```rust
1857                 test
1858                 ```
1859
1860                 ```rust
1861                 pub struct Bar
1862                 ```
1863
1864                 ---
1865
1866                 [external](https://www.google.com)
1867             "#]],
1868         );
1869     }
1870
1871     // Check that we don't rewrite links which we can't identify
1872     #[test]
1873     fn test_hover_unknown_target() {
1874         check(
1875             r#"
1876 pub struct Foo;
1877 /// [baz](Baz)
1878 pub struct B<|>ar
1879 "#,
1880             expect![[r#"
1881                 *Bar*
1882
1883                 ```rust
1884                 test
1885                 ```
1886
1887                 ```rust
1888                 pub struct Bar
1889                 ```
1890
1891                 ---
1892
1893                 [baz](Baz)
1894             "#]],
1895         );
1896     }
1897
1898     #[test]
1899     fn test_doc_links_enum_variant() {
1900         check(
1901             r#"
1902 enum E {
1903     /// [E]
1904     V<|> { field: i32 }
1905 }
1906 "#,
1907             expect![[r#"
1908                 *V*
1909
1910                 ```rust
1911                 test::E
1912                 ```
1913
1914                 ```rust
1915                 V
1916                 ```
1917
1918                 ---
1919
1920                 [E](https://docs.rs/test/*/test/enum.E.html)
1921             "#]],
1922         );
1923     }
1924
1925     #[test]
1926     fn test_doc_links_field() {
1927         check(
1928             r#"
1929 struct S {
1930     /// [`S`]
1931     field<|>: i32
1932 }
1933 "#,
1934             expect![[r#"
1935                 *field*
1936
1937                 ```rust
1938                 test::S
1939                 ```
1940
1941                 ```rust
1942                 field: i32
1943                 ```
1944
1945                 ---
1946
1947                 [`S`](https://docs.rs/test/*/test/struct.S.html)
1948             "#]],
1949         );
1950     }
1951
1952     #[test]
1953     fn test_hover_no_links() {
1954         check_hover_no_links(
1955             r#"
1956 /// Test cases:
1957 /// case 1.  bare URL: https://www.example.com/
1958 /// case 2.  inline URL with title: [example](https://www.example.com/)
1959 /// case 3.  code refrence: [`Result`]
1960 /// case 4.  code refrence but miss footnote: [`String`]
1961 /// case 5.  autolink: <http://www.example.com/>
1962 /// case 6.  email address: <test@example.com>
1963 /// case 7.  refrence: [example][example]
1964 /// case 8.  collapsed link: [example][]
1965 /// case 9.  shortcut link: [example]
1966 /// case 10. inline without URL: [example]()
1967 /// case 11. refrence: [foo][foo]
1968 /// case 12. refrence: [foo][bar]
1969 /// case 13. collapsed link: [foo][]
1970 /// case 14. shortcut link: [foo]
1971 /// case 15. inline without URL: [foo]()
1972 /// case 16. just escaped text: \[foo]
1973 /// case 17. inline link: [Foo](foo::Foo)
1974 ///
1975 /// [`Result`]: ../../std/result/enum.Result.html
1976 /// [^example]: https://www.example.com/
1977 pub fn fo<|>o() {}
1978 "#,
1979             expect![[r#"
1980                 *foo*
1981
1982                 ```rust
1983                 test
1984                 ```
1985
1986                 ```rust
1987                 pub fn foo()
1988                 ```
1989
1990                 ---
1991
1992                 Test cases:
1993                 case 1.  bare URL: https://www.example.com/
1994                 case 2.  inline URL with title: [example](https://www.example.com/)
1995                 case 3.  code refrence: `Result`
1996                 case 4.  code refrence but miss footnote: `String`
1997                 case 5.  autolink: http://www.example.com/
1998                 case 6.  email address: test@example.com
1999                 case 7.  refrence: example
2000                 case 8.  collapsed link: example
2001                 case 9.  shortcut link: example
2002                 case 10. inline without URL: example
2003                 case 11. refrence: foo
2004                 case 12. refrence: foo
2005                 case 13. collapsed link: foo
2006                 case 14. shortcut link: foo
2007                 case 15. inline without URL: foo
2008                 case 16. just escaped text: \[foo]
2009                 case 17. inline link: Foo
2010
2011                 [^example]: https://www.example.com/
2012             "#]],
2013         );
2014     }
2015
2016     #[test]
2017     fn test_hover_macro_generated_struct_fn_doc_comment() {
2018         mark::check!(hover_macro_generated_struct_fn_doc_comment);
2019
2020         check(
2021             r#"
2022 macro_rules! bar {
2023     () => {
2024         struct Bar;
2025         impl Bar {
2026             /// Do the foo
2027             fn foo(&self) {}
2028         }
2029     }
2030 }
2031
2032 bar!();
2033
2034 fn foo() { let bar = Bar; bar.fo<|>o(); }
2035 "#,
2036             expect![[r#"
2037                 *foo*
2038
2039                 ```rust
2040                 test::Bar
2041                 ```
2042
2043                 ```rust
2044                 fn foo(&self)
2045                 ```
2046
2047                 ---
2048
2049                 Do the foo
2050             "#]],
2051         );
2052     }
2053
2054     #[test]
2055     fn test_hover_macro_generated_struct_fn_doc_attr() {
2056         mark::check!(hover_macro_generated_struct_fn_doc_attr);
2057
2058         check(
2059             r#"
2060 macro_rules! bar {
2061     () => {
2062         struct Bar;
2063         impl Bar {
2064             #[doc = "Do the foo"]
2065             fn foo(&self) {}
2066         }
2067     }
2068 }
2069
2070 bar!();
2071
2072 fn foo() { let bar = Bar; bar.fo<|>o(); }
2073 "#,
2074             expect![[r#"
2075                 *foo*
2076
2077                 ```rust
2078                 test::Bar
2079                 ```
2080
2081                 ```rust
2082                 fn foo(&self)
2083                 ```
2084
2085                 ---
2086
2087                 Do the foo
2088             "#]],
2089         );
2090     }
2091
2092     #[test]
2093     fn test_hover_trait_has_impl_action() {
2094         check_actions(
2095             r#"trait foo<|>() {}"#,
2096             expect![[r#"
2097                 [
2098                     Implementaion(
2099                         FilePosition {
2100                             file_id: FileId(
2101                                 0,
2102                             ),
2103                             offset: 6,
2104                         },
2105                     ),
2106                 ]
2107             "#]],
2108         );
2109     }
2110
2111     #[test]
2112     fn test_hover_struct_has_impl_action() {
2113         check_actions(
2114             r"struct foo<|>() {}",
2115             expect![[r#"
2116                 [
2117                     Implementaion(
2118                         FilePosition {
2119                             file_id: FileId(
2120                                 0,
2121                             ),
2122                             offset: 7,
2123                         },
2124                     ),
2125                 ]
2126             "#]],
2127         );
2128     }
2129
2130     #[test]
2131     fn test_hover_union_has_impl_action() {
2132         check_actions(
2133             r#"union foo<|>() {}"#,
2134             expect![[r#"
2135                 [
2136                     Implementaion(
2137                         FilePosition {
2138                             file_id: FileId(
2139                                 0,
2140                             ),
2141                             offset: 6,
2142                         },
2143                     ),
2144                 ]
2145             "#]],
2146         );
2147     }
2148
2149     #[test]
2150     fn test_hover_enum_has_impl_action() {
2151         check_actions(
2152             r"enum foo<|>() { A, B }",
2153             expect![[r#"
2154                 [
2155                     Implementaion(
2156                         FilePosition {
2157                             file_id: FileId(
2158                                 0,
2159                             ),
2160                             offset: 5,
2161                         },
2162                     ),
2163                 ]
2164             "#]],
2165         );
2166     }
2167
2168     #[test]
2169     fn test_hover_test_has_action() {
2170         check_actions(
2171             r#"
2172 #[test]
2173 fn foo_<|>test() {}
2174 "#,
2175             expect![[r#"
2176                 [
2177                     Runnable(
2178                         Runnable {
2179                             nav: NavigationTarget {
2180                                 file_id: FileId(
2181                                     0,
2182                                 ),
2183                                 full_range: 0..24,
2184                                 focus_range: Some(
2185                                     11..19,
2186                                 ),
2187                                 name: "foo_test",
2188                                 kind: FN,
2189                                 container_name: None,
2190                                 description: None,
2191                                 docs: None,
2192                             },
2193                             kind: Test {
2194                                 test_id: Path(
2195                                     "foo_test",
2196                                 ),
2197                                 attr: TestAttr {
2198                                     ignore: false,
2199                                 },
2200                             },
2201                             cfg: None,
2202                         },
2203                     ),
2204                 ]
2205             "#]],
2206         );
2207     }
2208
2209     #[test]
2210     fn test_hover_test_mod_has_action() {
2211         check_actions(
2212             r#"
2213 mod tests<|> {
2214     #[test]
2215     fn foo_test() {}
2216 }
2217 "#,
2218             expect![[r#"
2219                 [
2220                     Runnable(
2221                         Runnable {
2222                             nav: NavigationTarget {
2223                                 file_id: FileId(
2224                                     0,
2225                                 ),
2226                                 full_range: 0..46,
2227                                 focus_range: Some(
2228                                     4..9,
2229                                 ),
2230                                 name: "tests",
2231                                 kind: MODULE,
2232                                 container_name: None,
2233                                 description: None,
2234                                 docs: None,
2235                             },
2236                             kind: TestMod {
2237                                 path: "tests",
2238                             },
2239                             cfg: None,
2240                         },
2241                     ),
2242                 ]
2243             "#]],
2244         );
2245     }
2246
2247     #[test]
2248     fn test_hover_struct_has_goto_type_action() {
2249         check_actions(
2250             r#"
2251 struct S{ f1: u32 }
2252
2253 fn main() { let s<|>t = S{ f1:0 }; }
2254             "#,
2255             expect![[r#"
2256                 [
2257                     GoToType(
2258                         [
2259                             HoverGotoTypeData {
2260                                 mod_path: "test::S",
2261                                 nav: NavigationTarget {
2262                                     file_id: FileId(
2263                                         0,
2264                                     ),
2265                                     full_range: 0..19,
2266                                     focus_range: Some(
2267                                         7..8,
2268                                     ),
2269                                     name: "S",
2270                                     kind: STRUCT,
2271                                     container_name: None,
2272                                     description: Some(
2273                                         "struct S",
2274                                     ),
2275                                     docs: None,
2276                                 },
2277                             },
2278                         ],
2279                     ),
2280                 ]
2281             "#]],
2282         );
2283     }
2284
2285     #[test]
2286     fn test_hover_generic_struct_has_goto_type_actions() {
2287         check_actions(
2288             r#"
2289 struct Arg(u32);
2290 struct S<T>{ f1: T }
2291
2292 fn main() { let s<|>t = S{ f1:Arg(0) }; }
2293 "#,
2294             expect![[r#"
2295                 [
2296                     GoToType(
2297                         [
2298                             HoverGotoTypeData {
2299                                 mod_path: "test::S",
2300                                 nav: NavigationTarget {
2301                                     file_id: FileId(
2302                                         0,
2303                                     ),
2304                                     full_range: 17..37,
2305                                     focus_range: Some(
2306                                         24..25,
2307                                     ),
2308                                     name: "S",
2309                                     kind: STRUCT,
2310                                     container_name: None,
2311                                     description: Some(
2312                                         "struct S",
2313                                     ),
2314                                     docs: None,
2315                                 },
2316                             },
2317                             HoverGotoTypeData {
2318                                 mod_path: "test::Arg",
2319                                 nav: NavigationTarget {
2320                                     file_id: FileId(
2321                                         0,
2322                                     ),
2323                                     full_range: 0..16,
2324                                     focus_range: Some(
2325                                         7..10,
2326                                     ),
2327                                     name: "Arg",
2328                                     kind: STRUCT,
2329                                     container_name: None,
2330                                     description: Some(
2331                                         "struct Arg",
2332                                     ),
2333                                     docs: None,
2334                                 },
2335                             },
2336                         ],
2337                     ),
2338                 ]
2339             "#]],
2340         );
2341     }
2342
2343     #[test]
2344     fn test_hover_generic_struct_has_flattened_goto_type_actions() {
2345         check_actions(
2346             r#"
2347 struct Arg(u32);
2348 struct S<T>{ f1: T }
2349
2350 fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
2351             "#,
2352             expect![[r#"
2353                 [
2354                     GoToType(
2355                         [
2356                             HoverGotoTypeData {
2357                                 mod_path: "test::S",
2358                                 nav: NavigationTarget {
2359                                     file_id: FileId(
2360                                         0,
2361                                     ),
2362                                     full_range: 17..37,
2363                                     focus_range: Some(
2364                                         24..25,
2365                                     ),
2366                                     name: "S",
2367                                     kind: STRUCT,
2368                                     container_name: None,
2369                                     description: Some(
2370                                         "struct S",
2371                                     ),
2372                                     docs: None,
2373                                 },
2374                             },
2375                             HoverGotoTypeData {
2376                                 mod_path: "test::Arg",
2377                                 nav: NavigationTarget {
2378                                     file_id: FileId(
2379                                         0,
2380                                     ),
2381                                     full_range: 0..16,
2382                                     focus_range: Some(
2383                                         7..10,
2384                                     ),
2385                                     name: "Arg",
2386                                     kind: STRUCT,
2387                                     container_name: None,
2388                                     description: Some(
2389                                         "struct Arg",
2390                                     ),
2391                                     docs: None,
2392                                 },
2393                             },
2394                         ],
2395                     ),
2396                 ]
2397             "#]],
2398         );
2399     }
2400
2401     #[test]
2402     fn test_hover_tuple_has_goto_type_actions() {
2403         check_actions(
2404             r#"
2405 struct A(u32);
2406 struct B(u32);
2407 mod M {
2408     pub struct C(u32);
2409 }
2410
2411 fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
2412 "#,
2413             expect![[r#"
2414                 [
2415                     GoToType(
2416                         [
2417                             HoverGotoTypeData {
2418                                 mod_path: "test::A",
2419                                 nav: NavigationTarget {
2420                                     file_id: FileId(
2421                                         0,
2422                                     ),
2423                                     full_range: 0..14,
2424                                     focus_range: Some(
2425                                         7..8,
2426                                     ),
2427                                     name: "A",
2428                                     kind: STRUCT,
2429                                     container_name: None,
2430                                     description: Some(
2431                                         "struct A",
2432                                     ),
2433                                     docs: None,
2434                                 },
2435                             },
2436                             HoverGotoTypeData {
2437                                 mod_path: "test::B",
2438                                 nav: NavigationTarget {
2439                                     file_id: FileId(
2440                                         0,
2441                                     ),
2442                                     full_range: 15..29,
2443                                     focus_range: Some(
2444                                         22..23,
2445                                     ),
2446                                     name: "B",
2447                                     kind: STRUCT,
2448                                     container_name: None,
2449                                     description: Some(
2450                                         "struct B",
2451                                     ),
2452                                     docs: None,
2453                                 },
2454                             },
2455                             HoverGotoTypeData {
2456                                 mod_path: "test::M::C",
2457                                 nav: NavigationTarget {
2458                                     file_id: FileId(
2459                                         0,
2460                                     ),
2461                                     full_range: 42..60,
2462                                     focus_range: Some(
2463                                         53..54,
2464                                     ),
2465                                     name: "C",
2466                                     kind: STRUCT,
2467                                     container_name: None,
2468                                     description: Some(
2469                                         "pub struct C",
2470                                     ),
2471                                     docs: None,
2472                                 },
2473                             },
2474                         ],
2475                     ),
2476                 ]
2477             "#]],
2478         );
2479     }
2480
2481     #[test]
2482     fn test_hover_return_impl_trait_has_goto_type_action() {
2483         check_actions(
2484             r#"
2485 trait Foo {}
2486 fn foo() -> impl Foo {}
2487
2488 fn main() { let s<|>t = foo(); }
2489 "#,
2490             expect![[r#"
2491                 [
2492                     GoToType(
2493                         [
2494                             HoverGotoTypeData {
2495                                 mod_path: "test::Foo",
2496                                 nav: NavigationTarget {
2497                                     file_id: FileId(
2498                                         0,
2499                                     ),
2500                                     full_range: 0..12,
2501                                     focus_range: Some(
2502                                         6..9,
2503                                     ),
2504                                     name: "Foo",
2505                                     kind: TRAIT,
2506                                     container_name: None,
2507                                     description: Some(
2508                                         "trait Foo",
2509                                     ),
2510                                     docs: None,
2511                                 },
2512                             },
2513                         ],
2514                     ),
2515                 ]
2516             "#]],
2517         );
2518     }
2519
2520     #[test]
2521     fn test_hover_generic_return_impl_trait_has_goto_type_action() {
2522         check_actions(
2523             r#"
2524 trait Foo<T> {}
2525 struct S;
2526 fn foo() -> impl Foo<S> {}
2527
2528 fn main() { let s<|>t = foo(); }
2529 "#,
2530             expect![[r#"
2531                 [
2532                     GoToType(
2533                         [
2534                             HoverGotoTypeData {
2535                                 mod_path: "test::Foo",
2536                                 nav: NavigationTarget {
2537                                     file_id: FileId(
2538                                         0,
2539                                     ),
2540                                     full_range: 0..15,
2541                                     focus_range: Some(
2542                                         6..9,
2543                                     ),
2544                                     name: "Foo",
2545                                     kind: TRAIT,
2546                                     container_name: None,
2547                                     description: Some(
2548                                         "trait Foo",
2549                                     ),
2550                                     docs: None,
2551                                 },
2552                             },
2553                             HoverGotoTypeData {
2554                                 mod_path: "test::S",
2555                                 nav: NavigationTarget {
2556                                     file_id: FileId(
2557                                         0,
2558                                     ),
2559                                     full_range: 16..25,
2560                                     focus_range: Some(
2561                                         23..24,
2562                                     ),
2563                                     name: "S",
2564                                     kind: STRUCT,
2565                                     container_name: None,
2566                                     description: Some(
2567                                         "struct S",
2568                                     ),
2569                                     docs: None,
2570                                 },
2571                             },
2572                         ],
2573                     ),
2574                 ]
2575             "#]],
2576         );
2577     }
2578
2579     #[test]
2580     fn test_hover_return_impl_traits_has_goto_type_action() {
2581         check_actions(
2582             r#"
2583 trait Foo {}
2584 trait Bar {}
2585 fn foo() -> impl Foo + Bar {}
2586
2587 fn main() { let s<|>t = foo(); }
2588             "#,
2589             expect![[r#"
2590                 [
2591                     GoToType(
2592                         [
2593                             HoverGotoTypeData {
2594                                 mod_path: "test::Foo",
2595                                 nav: NavigationTarget {
2596                                     file_id: FileId(
2597                                         0,
2598                                     ),
2599                                     full_range: 0..12,
2600                                     focus_range: Some(
2601                                         6..9,
2602                                     ),
2603                                     name: "Foo",
2604                                     kind: TRAIT,
2605                                     container_name: None,
2606                                     description: Some(
2607                                         "trait Foo",
2608                                     ),
2609                                     docs: None,
2610                                 },
2611                             },
2612                             HoverGotoTypeData {
2613                                 mod_path: "test::Bar",
2614                                 nav: NavigationTarget {
2615                                     file_id: FileId(
2616                                         0,
2617                                     ),
2618                                     full_range: 13..25,
2619                                     focus_range: Some(
2620                                         19..22,
2621                                     ),
2622                                     name: "Bar",
2623                                     kind: TRAIT,
2624                                     container_name: None,
2625                                     description: Some(
2626                                         "trait Bar",
2627                                     ),
2628                                     docs: None,
2629                                 },
2630                             },
2631                         ],
2632                     ),
2633                 ]
2634             "#]],
2635         );
2636     }
2637
2638     #[test]
2639     fn test_hover_generic_return_impl_traits_has_goto_type_action() {
2640         check_actions(
2641             r#"
2642 trait Foo<T> {}
2643 trait Bar<T> {}
2644 struct S1 {}
2645 struct S2 {}
2646
2647 fn foo() -> impl Foo<S1> + Bar<S2> {}
2648
2649 fn main() { let s<|>t = foo(); }
2650 "#,
2651             expect![[r#"
2652                 [
2653                     GoToType(
2654                         [
2655                             HoverGotoTypeData {
2656                                 mod_path: "test::Foo",
2657                                 nav: NavigationTarget {
2658                                     file_id: FileId(
2659                                         0,
2660                                     ),
2661                                     full_range: 0..15,
2662                                     focus_range: Some(
2663                                         6..9,
2664                                     ),
2665                                     name: "Foo",
2666                                     kind: TRAIT,
2667                                     container_name: None,
2668                                     description: Some(
2669                                         "trait Foo",
2670                                     ),
2671                                     docs: None,
2672                                 },
2673                             },
2674                             HoverGotoTypeData {
2675                                 mod_path: "test::Bar",
2676                                 nav: NavigationTarget {
2677                                     file_id: FileId(
2678                                         0,
2679                                     ),
2680                                     full_range: 16..31,
2681                                     focus_range: Some(
2682                                         22..25,
2683                                     ),
2684                                     name: "Bar",
2685                                     kind: TRAIT,
2686                                     container_name: None,
2687                                     description: Some(
2688                                         "trait Bar",
2689                                     ),
2690                                     docs: None,
2691                                 },
2692                             },
2693                             HoverGotoTypeData {
2694                                 mod_path: "test::S1",
2695                                 nav: NavigationTarget {
2696                                     file_id: FileId(
2697                                         0,
2698                                     ),
2699                                     full_range: 32..44,
2700                                     focus_range: Some(
2701                                         39..41,
2702                                     ),
2703                                     name: "S1",
2704                                     kind: STRUCT,
2705                                     container_name: None,
2706                                     description: Some(
2707                                         "struct S1",
2708                                     ),
2709                                     docs: None,
2710                                 },
2711                             },
2712                             HoverGotoTypeData {
2713                                 mod_path: "test::S2",
2714                                 nav: NavigationTarget {
2715                                     file_id: FileId(
2716                                         0,
2717                                     ),
2718                                     full_range: 45..57,
2719                                     focus_range: Some(
2720                                         52..54,
2721                                     ),
2722                                     name: "S2",
2723                                     kind: STRUCT,
2724                                     container_name: None,
2725                                     description: Some(
2726                                         "struct S2",
2727                                     ),
2728                                     docs: None,
2729                                 },
2730                             },
2731                         ],
2732                     ),
2733                 ]
2734             "#]],
2735         );
2736     }
2737
2738     #[test]
2739     fn test_hover_arg_impl_trait_has_goto_type_action() {
2740         check_actions(
2741             r#"
2742 trait Foo {}
2743 fn foo(ar<|>g: &impl Foo) {}
2744 "#,
2745             expect![[r#"
2746                 [
2747                     GoToType(
2748                         [
2749                             HoverGotoTypeData {
2750                                 mod_path: "test::Foo",
2751                                 nav: NavigationTarget {
2752                                     file_id: FileId(
2753                                         0,
2754                                     ),
2755                                     full_range: 0..12,
2756                                     focus_range: Some(
2757                                         6..9,
2758                                     ),
2759                                     name: "Foo",
2760                                     kind: TRAIT,
2761                                     container_name: None,
2762                                     description: Some(
2763                                         "trait Foo",
2764                                     ),
2765                                     docs: None,
2766                                 },
2767                             },
2768                         ],
2769                     ),
2770                 ]
2771             "#]],
2772         );
2773     }
2774
2775     #[test]
2776     fn test_hover_arg_impl_traits_has_goto_type_action() {
2777         check_actions(
2778             r#"
2779 trait Foo {}
2780 trait Bar<T> {}
2781 struct S{}
2782
2783 fn foo(ar<|>g: &impl Foo + Bar<S>) {}
2784 "#,
2785             expect![[r#"
2786                 [
2787                     GoToType(
2788                         [
2789                             HoverGotoTypeData {
2790                                 mod_path: "test::Foo",
2791                                 nav: NavigationTarget {
2792                                     file_id: FileId(
2793                                         0,
2794                                     ),
2795                                     full_range: 0..12,
2796                                     focus_range: Some(
2797                                         6..9,
2798                                     ),
2799                                     name: "Foo",
2800                                     kind: TRAIT,
2801                                     container_name: None,
2802                                     description: Some(
2803                                         "trait Foo",
2804                                     ),
2805                                     docs: None,
2806                                 },
2807                             },
2808                             HoverGotoTypeData {
2809                                 mod_path: "test::Bar",
2810                                 nav: NavigationTarget {
2811                                     file_id: FileId(
2812                                         0,
2813                                     ),
2814                                     full_range: 13..28,
2815                                     focus_range: Some(
2816                                         19..22,
2817                                     ),
2818                                     name: "Bar",
2819                                     kind: TRAIT,
2820                                     container_name: None,
2821                                     description: Some(
2822                                         "trait Bar",
2823                                     ),
2824                                     docs: None,
2825                                 },
2826                             },
2827                             HoverGotoTypeData {
2828                                 mod_path: "test::S",
2829                                 nav: NavigationTarget {
2830                                     file_id: FileId(
2831                                         0,
2832                                     ),
2833                                     full_range: 29..39,
2834                                     focus_range: Some(
2835                                         36..37,
2836                                     ),
2837                                     name: "S",
2838                                     kind: STRUCT,
2839                                     container_name: None,
2840                                     description: Some(
2841                                         "struct S",
2842                                     ),
2843                                     docs: None,
2844                                 },
2845                             },
2846                         ],
2847                     ),
2848                 ]
2849             "#]],
2850         );
2851     }
2852
2853     #[test]
2854     fn test_hover_async_block_impl_trait_has_goto_type_action() {
2855         check_actions(
2856             r#"
2857 struct S;
2858 fn foo() {
2859     let fo<|>o = async { S };
2860 }
2861
2862 #[prelude_import] use future::*;
2863 mod future {
2864     #[lang = "future_trait"]
2865     pub trait Future { type Output; }
2866 }
2867 "#,
2868             expect![[r#"
2869                 [
2870                     GoToType(
2871                         [
2872                             HoverGotoTypeData {
2873                                 mod_path: "test::future::Future",
2874                                 nav: NavigationTarget {
2875                                     file_id: FileId(
2876                                         0,
2877                                     ),
2878                                     full_range: 101..163,
2879                                     focus_range: Some(
2880                                         140..146,
2881                                     ),
2882                                     name: "Future",
2883                                     kind: TRAIT,
2884                                     container_name: None,
2885                                     description: Some(
2886                                         "pub trait Future",
2887                                     ),
2888                                     docs: None,
2889                                 },
2890                             },
2891                             HoverGotoTypeData {
2892                                 mod_path: "test::S",
2893                                 nav: NavigationTarget {
2894                                     file_id: FileId(
2895                                         0,
2896                                     ),
2897                                     full_range: 0..9,
2898                                     focus_range: Some(
2899                                         7..8,
2900                                     ),
2901                                     name: "S",
2902                                     kind: STRUCT,
2903                                     container_name: None,
2904                                     description: Some(
2905                                         "struct S",
2906                                     ),
2907                                     docs: None,
2908                                 },
2909                             },
2910                         ],
2911                     ),
2912                 ]
2913             "#]],
2914         );
2915     }
2916
2917     #[test]
2918     fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
2919         check_actions(
2920             r#"
2921 trait Foo<T> {}
2922 struct S {}
2923 fn foo(ar<|>g: &impl Foo<S>) {}
2924 "#,
2925             expect![[r#"
2926                 [
2927                     GoToType(
2928                         [
2929                             HoverGotoTypeData {
2930                                 mod_path: "test::Foo",
2931                                 nav: NavigationTarget {
2932                                     file_id: FileId(
2933                                         0,
2934                                     ),
2935                                     full_range: 0..15,
2936                                     focus_range: Some(
2937                                         6..9,
2938                                     ),
2939                                     name: "Foo",
2940                                     kind: TRAIT,
2941                                     container_name: None,
2942                                     description: Some(
2943                                         "trait Foo",
2944                                     ),
2945                                     docs: None,
2946                                 },
2947                             },
2948                             HoverGotoTypeData {
2949                                 mod_path: "test::S",
2950                                 nav: NavigationTarget {
2951                                     file_id: FileId(
2952                                         0,
2953                                     ),
2954                                     full_range: 16..27,
2955                                     focus_range: Some(
2956                                         23..24,
2957                                     ),
2958                                     name: "S",
2959                                     kind: STRUCT,
2960                                     container_name: None,
2961                                     description: Some(
2962                                         "struct S",
2963                                     ),
2964                                     docs: None,
2965                                 },
2966                             },
2967                         ],
2968                     ),
2969                 ]
2970             "#]],
2971         );
2972     }
2973
2974     #[test]
2975     fn test_hover_dyn_return_has_goto_type_action() {
2976         check_actions(
2977             r#"
2978 trait Foo {}
2979 struct S;
2980 impl Foo for S {}
2981
2982 struct B<T>{}
2983 fn foo() -> B<dyn Foo> {}
2984
2985 fn main() { let s<|>t = foo(); }
2986 "#,
2987             expect![[r#"
2988                 [
2989                     GoToType(
2990                         [
2991                             HoverGotoTypeData {
2992                                 mod_path: "test::B",
2993                                 nav: NavigationTarget {
2994                                     file_id: FileId(
2995                                         0,
2996                                     ),
2997                                     full_range: 42..55,
2998                                     focus_range: Some(
2999                                         49..50,
3000                                     ),
3001                                     name: "B",
3002                                     kind: STRUCT,
3003                                     container_name: None,
3004                                     description: Some(
3005                                         "struct B",
3006                                     ),
3007                                     docs: None,
3008                                 },
3009                             },
3010                             HoverGotoTypeData {
3011                                 mod_path: "test::Foo",
3012                                 nav: NavigationTarget {
3013                                     file_id: FileId(
3014                                         0,
3015                                     ),
3016                                     full_range: 0..12,
3017                                     focus_range: Some(
3018                                         6..9,
3019                                     ),
3020                                     name: "Foo",
3021                                     kind: TRAIT,
3022                                     container_name: None,
3023                                     description: Some(
3024                                         "trait Foo",
3025                                     ),
3026                                     docs: None,
3027                                 },
3028                             },
3029                         ],
3030                     ),
3031                 ]
3032             "#]],
3033         );
3034     }
3035
3036     #[test]
3037     fn test_hover_dyn_arg_has_goto_type_action() {
3038         check_actions(
3039             r#"
3040 trait Foo {}
3041 fn foo(ar<|>g: &dyn Foo) {}
3042 "#,
3043             expect![[r#"
3044                 [
3045                     GoToType(
3046                         [
3047                             HoverGotoTypeData {
3048                                 mod_path: "test::Foo",
3049                                 nav: NavigationTarget {
3050                                     file_id: FileId(
3051                                         0,
3052                                     ),
3053                                     full_range: 0..12,
3054                                     focus_range: Some(
3055                                         6..9,
3056                                     ),
3057                                     name: "Foo",
3058                                     kind: TRAIT,
3059                                     container_name: None,
3060                                     description: Some(
3061                                         "trait Foo",
3062                                     ),
3063                                     docs: None,
3064                                 },
3065                             },
3066                         ],
3067                     ),
3068                 ]
3069             "#]],
3070         );
3071     }
3072
3073     #[test]
3074     fn test_hover_generic_dyn_arg_has_goto_type_action() {
3075         check_actions(
3076             r#"
3077 trait Foo<T> {}
3078 struct S {}
3079 fn foo(ar<|>g: &dyn Foo<S>) {}
3080 "#,
3081             expect![[r#"
3082                 [
3083                     GoToType(
3084                         [
3085                             HoverGotoTypeData {
3086                                 mod_path: "test::Foo",
3087                                 nav: NavigationTarget {
3088                                     file_id: FileId(
3089                                         0,
3090                                     ),
3091                                     full_range: 0..15,
3092                                     focus_range: Some(
3093                                         6..9,
3094                                     ),
3095                                     name: "Foo",
3096                                     kind: TRAIT,
3097                                     container_name: None,
3098                                     description: Some(
3099                                         "trait Foo",
3100                                     ),
3101                                     docs: None,
3102                                 },
3103                             },
3104                             HoverGotoTypeData {
3105                                 mod_path: "test::S",
3106                                 nav: NavigationTarget {
3107                                     file_id: FileId(
3108                                         0,
3109                                     ),
3110                                     full_range: 16..27,
3111                                     focus_range: Some(
3112                                         23..24,
3113                                     ),
3114                                     name: "S",
3115                                     kind: STRUCT,
3116                                     container_name: None,
3117                                     description: Some(
3118                                         "struct S",
3119                                     ),
3120                                     docs: None,
3121                                 },
3122                             },
3123                         ],
3124                     ),
3125                 ]
3126             "#]],
3127         );
3128     }
3129
3130     #[test]
3131     fn test_hover_goto_type_action_links_order() {
3132         check_actions(
3133             r#"
3134 trait ImplTrait<T> {}
3135 trait DynTrait<T> {}
3136 struct B<T> {}
3137 struct S {}
3138
3139 fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3140             "#,
3141             expect![[r#"
3142                 [
3143                     GoToType(
3144                         [
3145                             HoverGotoTypeData {
3146                                 mod_path: "test::ImplTrait",
3147                                 nav: NavigationTarget {
3148                                     file_id: FileId(
3149                                         0,
3150                                     ),
3151                                     full_range: 0..21,
3152                                     focus_range: Some(
3153                                         6..15,
3154                                     ),
3155                                     name: "ImplTrait",
3156                                     kind: TRAIT,
3157                                     container_name: None,
3158                                     description: Some(
3159                                         "trait ImplTrait",
3160                                     ),
3161                                     docs: None,
3162                                 },
3163                             },
3164                             HoverGotoTypeData {
3165                                 mod_path: "test::B",
3166                                 nav: NavigationTarget {
3167                                     file_id: FileId(
3168                                         0,
3169                                     ),
3170                                     full_range: 43..57,
3171                                     focus_range: Some(
3172                                         50..51,
3173                                     ),
3174                                     name: "B",
3175                                     kind: STRUCT,
3176                                     container_name: None,
3177                                     description: Some(
3178                                         "struct B",
3179                                     ),
3180                                     docs: None,
3181                                 },
3182                             },
3183                             HoverGotoTypeData {
3184                                 mod_path: "test::DynTrait",
3185                                 nav: NavigationTarget {
3186                                     file_id: FileId(
3187                                         0,
3188                                     ),
3189                                     full_range: 22..42,
3190                                     focus_range: Some(
3191                                         28..36,
3192                                     ),
3193                                     name: "DynTrait",
3194                                     kind: TRAIT,
3195                                     container_name: None,
3196                                     description: Some(
3197                                         "trait DynTrait",
3198                                     ),
3199                                     docs: None,
3200                                 },
3201                             },
3202                             HoverGotoTypeData {
3203                                 mod_path: "test::S",
3204                                 nav: NavigationTarget {
3205                                     file_id: FileId(
3206                                         0,
3207                                     ),
3208                                     full_range: 58..69,
3209                                     focus_range: Some(
3210                                         65..66,
3211                                     ),
3212                                     name: "S",
3213                                     kind: STRUCT,
3214                                     container_name: None,
3215                                     description: Some(
3216                                         "struct S",
3217                                     ),
3218                                     docs: None,
3219                                 },
3220                             },
3221                         ],
3222                     ),
3223                 ]
3224             "#]],
3225         );
3226     }
3227
3228     #[test]
3229     fn test_hover_associated_type_has_goto_type_action() {
3230         check_actions(
3231             r#"
3232 trait Foo {
3233     type Item;
3234     fn get(self) -> Self::Item {}
3235 }
3236
3237 struct Bar{}
3238 struct S{}
3239
3240 impl Foo for S { type Item = Bar; }
3241
3242 fn test() -> impl Foo { S {} }
3243
3244 fn main() { let s<|>t = test().get(); }
3245 "#,
3246             expect![[r#"
3247                 [
3248                     GoToType(
3249                         [
3250                             HoverGotoTypeData {
3251                                 mod_path: "test::Foo",
3252                                 nav: NavigationTarget {
3253                                     file_id: FileId(
3254                                         0,
3255                                     ),
3256                                     full_range: 0..62,
3257                                     focus_range: Some(
3258                                         6..9,
3259                                     ),
3260                                     name: "Foo",
3261                                     kind: TRAIT,
3262                                     container_name: None,
3263                                     description: Some(
3264                                         "trait Foo",
3265                                     ),
3266                                     docs: None,
3267                                 },
3268                             },
3269                         ],
3270                     ),
3271                 ]
3272             "#]],
3273         );
3274     }
3275
3276     #[test]
3277     fn hover_displays_normalized_crate_names() {
3278         check(
3279             r#"
3280 //- /lib.rs crate:name-with-dashes
3281 pub mod wrapper {
3282     pub struct Thing { x: u32 }
3283
3284     impl Thing {
3285         pub fn new() -> Thing { Thing { x: 0 } }
3286     }
3287 }
3288
3289 //- /main.rs crate:main deps:name-with-dashes
3290 fn main() { let foo_test = name_with_dashes::wrapper::Thing::new<|>(); }
3291 "#,
3292             expect![[r#"
3293             *new*
3294
3295             ```rust
3296             name_with_dashes::wrapper::Thing
3297             ```
3298
3299             ```rust
3300             pub fn new() -> Thing
3301             ```
3302             "#]],
3303         )
3304     }
3305
3306     #[test]
3307     fn hover_field_pat_shorthand_ref_match_ergonomics() {
3308         check(
3309             r#"
3310 struct S {
3311     f: i32,
3312 }
3313
3314 fn main() {
3315     let s = S { f: 0 };
3316     let S { f<|> } = &s;
3317 }
3318 "#,
3319             expect![[r#"
3320                 *f*
3321
3322                 ```rust
3323                 &i32
3324                 ```
3325             "#]],
3326         );
3327     }
3328
3329     #[test]
3330     fn hover_self_param_shows_type() {
3331         check(
3332             r#"
3333 struct Foo {}
3334 impl Foo {
3335     fn bar(&sel<|>f) {}
3336 }
3337 "#,
3338             expect![[r#"
3339                 *&self*
3340                 ```rust
3341                 &Foo
3342                 ```
3343             "#]],
3344         );
3345     }
3346
3347     #[test]
3348     fn hover_self_param_shows_type_for_arbitrary_self_type() {
3349         check(
3350             r#"
3351 struct Arc<T>(T);
3352 struct Foo {}
3353 impl Foo {
3354     fn bar(sel<|>f: Arc<Foo>) {}
3355 }
3356 "#,
3357             expect![[r#"
3358                 *self: Arc<Foo>*
3359                 ```rust
3360                 Arc<Foo>
3361                 ```
3362             "#]],
3363         );
3364     }
3365
3366     #[test]
3367     fn hover_doc_outer_inner() {
3368         check(
3369             r#"
3370 /// Be quick;
3371 mod Foo<|> {
3372     //! time is mana
3373
3374     /// This comment belongs to the function
3375     fn foo() {}
3376 }
3377 "#,
3378             expect![[r#"
3379                 *Foo*
3380
3381                 ```rust
3382                 test
3383                 ```
3384
3385                 ```rust
3386                 mod Foo
3387                 ```
3388
3389                 ---
3390
3391                 Be quick;
3392                 time is mana
3393             "#]],
3394         );
3395     }
3396
3397     #[test]
3398     fn hover_doc_outer_inner_attribue() {
3399         check(
3400             r#"
3401 #[doc = "Be quick;"]
3402 mod Foo<|> {
3403     #![doc = "time is mana"]
3404
3405     #[doc = "This comment belongs to the function"]
3406     fn foo() {}
3407 }
3408 "#,
3409             expect![[r#"
3410                 *Foo*
3411
3412                 ```rust
3413                 test
3414                 ```
3415
3416                 ```rust
3417                 mod Foo
3418                 ```
3419
3420                 ---
3421
3422                 Be quick;
3423                 time is mana
3424             "#]],
3425         );
3426     }
3427
3428     #[test]
3429     fn hover_comments_dont_highlight_parent() {
3430         check_hover_no_result(
3431             r#"
3432 fn no_hover() {
3433     // no<|>hover
3434 }
3435 "#,
3436         );
3437     }
3438 }