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