]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/hover.rs
Merge #7195
[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, TryToNav},
17     doc_links::{remove_links, rewrite_links},
18     markdown_remove::remove_markdown,
19     markup::Markup,
20     runnables::{runnable, runnable_fn},
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 HoverConfig {
35     pub const NO_ACTIONS: Self = Self {
36         implementations: false,
37         run: false,
38         debug: false,
39         goto_type_def: false,
40         links_in_hover: true,
41         markdown: true,
42     };
43
44     pub fn any(&self) -> bool {
45         self.implementations || self.runnable() || self.goto_type_def
46     }
47
48     pub fn none(&self) -> bool {
49         !self.any()
50     }
51
52     pub fn runnable(&self) -> bool {
53         self.run || self.debug
54     }
55 }
56
57 #[derive(Debug, Clone)]
58 pub enum HoverAction {
59     Runnable(Runnable),
60     Implementation(FilePosition),
61     GoToType(Vec<HoverGotoTypeData>),
62 }
63
64 #[derive(Debug, Clone, Eq, PartialEq)]
65 pub struct HoverGotoTypeData {
66     pub mod_path: String,
67     pub nav: NavigationTarget,
68 }
69
70 /// Contains the results when hovering over an item
71 #[derive(Debug, Default)]
72 pub struct HoverResult {
73     pub markup: Markup,
74     pub actions: Vec<HoverAction>,
75 }
76
77 // Feature: Hover
78 //
79 // Shows additional information, like type of an expression or documentation for definition when "focusing" code.
80 // Focusing is usually hovering with a mouse, but can also be triggered with a shortcut.
81 pub(crate) fn hover(
82     db: &RootDatabase,
83     position: FilePosition,
84     links_in_hover: bool,
85     markdown: bool,
86 ) -> Option<RangeInfo<HoverResult>> {
87     let sema = Semantics::new(db);
88     let file = sema.parse(position.file_id).syntax().clone();
89     let token = pick_best(file.token_at_offset(position.offset))?;
90     let token = sema.descend_into_macros(token);
91
92     let mut res = HoverResult::default();
93
94     let node = token.parent();
95     let definition = match_ast! {
96         match node {
97             ast::Name(name) => NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db)),
98             ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
99             ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime)
100                 .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)),
101             _ => None,
102         }
103     };
104     if let Some(definition) = definition {
105         if let Some(markup) = hover_for_definition(db, definition) {
106             let markup = markup.as_str();
107             let markup = if !markdown {
108                 remove_markdown(markup)
109             } else if links_in_hover {
110                 rewrite_links(db, markup, &definition)
111             } else {
112                 remove_links(markup)
113             };
114             res.markup = Markup::from(markup);
115             if let Some(action) = show_implementations_action(db, definition) {
116                 res.actions.push(action);
117             }
118
119             if let Some(action) = runnable_action(&sema, definition, position.file_id) {
120                 res.actions.push(action);
121             }
122
123             if let Some(action) = goto_type_action(db, definition) {
124                 res.actions.push(action);
125             }
126
127             let range = sema.original_range(&node).range;
128             return Some(RangeInfo::new(range, res));
129         }
130     }
131
132     if token.kind() == syntax::SyntaxKind::COMMENT {
133         // don't highlight the entire parent node on comment hover
134         return None;
135     }
136
137     let node = token.ancestors().find(|n| {
138         ast::Expr::can_cast(n.kind())
139             || ast::Pat::can_cast(n.kind())
140             || ast::SelfParam::can_cast(n.kind())
141     })?;
142
143     let ty = match_ast! {
144         match node {
145             ast::Expr(it) => sema.type_of_expr(&it)?,
146             ast::Pat(it) => sema.type_of_pat(&it)?,
147             ast::SelfParam(self_param) => sema.type_of_self(&self_param)?,
148             // If this node is a MACRO_CALL, it means that `descend_into_macros` failed to resolve.
149             // (e.g expanding a builtin macro). So we give up here.
150             ast::MacroCall(_it) => return None,
151             _ => return None,
152         }
153     };
154
155     res.markup = if markdown {
156         Markup::fenced_block(&ty.display(db))
157     } else {
158         ty.display(db).to_string().into()
159     };
160     let range = sema.original_range(&node).range;
161     Some(RangeInfo::new(range, res))
162 }
163
164 fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
165     fn to_action(nav_target: NavigationTarget) -> HoverAction {
166         HoverAction::Implementation(FilePosition {
167             file_id: nav_target.file_id,
168             offset: nav_target.focus_or_full_range().start(),
169         })
170     }
171
172     let adt = match def {
173         Definition::ModuleDef(ModuleDef::Trait(it)) => return it.try_to_nav(db).map(to_action),
174         Definition::ModuleDef(ModuleDef::Adt(it)) => Some(it),
175         Definition::SelfType(it) => it.target_ty(db).as_adt(),
176         _ => None,
177     }?;
178     match adt {
179         Adt::Struct(it) => it.try_to_nav(db),
180         Adt::Union(it) => it.try_to_nav(db),
181         Adt::Enum(it) => it.try_to_nav(db),
182     }
183     .map(to_action)
184 }
185
186 fn runnable_action(
187     sema: &Semantics<RootDatabase>,
188     def: Definition,
189     file_id: FileId,
190 ) -> Option<HoverAction> {
191     match def {
192         Definition::ModuleDef(it) => match it {
193             ModuleDef::Module(it) => match it.definition_source(sema.db).value {
194                 ModuleSource::Module(it) => {
195                     runnable(&sema, it.syntax().clone()).map(|it| HoverAction::Runnable(it))
196                 }
197                 _ => None,
198             },
199             ModuleDef::Function(func) => {
200                 let src = func.source(sema.db)?;
201                 if src.file_id != file_id.into() {
202                     mark::hit!(hover_macro_generated_struct_fn_doc_comment);
203                     mark::hit!(hover_macro_generated_struct_fn_doc_attr);
204                     return None;
205                 }
206
207                 runnable_fn(&sema, func).map(HoverAction::Runnable)
208             }
209             _ => None,
210         },
211         _ => None,
212     }
213 }
214
215 fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
216     let mut targets: Vec<ModuleDef> = Vec::new();
217     let mut push_new_def = |item: ModuleDef| {
218         if !targets.contains(&item) {
219             targets.push(item);
220         }
221     };
222
223     if let Definition::TypeParam(it) = def {
224         it.trait_bounds(db).into_iter().for_each(|it| push_new_def(it.into()));
225     } else {
226         let ty = match def {
227             Definition::Local(it) => it.ty(db),
228             Definition::ConstParam(it) => it.ty(db),
229             _ => return None,
230         };
231
232         ty.walk(db, |t| {
233             if let Some(adt) = t.as_adt() {
234                 push_new_def(adt.into());
235             } else if let Some(trait_) = t.as_dyn_trait() {
236                 push_new_def(trait_.into());
237             } else if let Some(traits) = t.as_impl_traits(db) {
238                 traits.into_iter().for_each(|it| push_new_def(it.into()));
239             } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
240                 push_new_def(trait_.into());
241             }
242         });
243     }
244
245     let targets = targets
246         .into_iter()
247         .filter_map(|it| {
248             Some(HoverGotoTypeData {
249                 mod_path: render_path(db, it.module(db)?, it.name(db).map(|name| name.to_string())),
250                 nav: it.try_to_nav(db)?,
251             })
252         })
253         .collect();
254
255     Some(HoverAction::GoToType(targets))
256 }
257
258 fn hover_markup(
259     docs: Option<String>,
260     desc: Option<String>,
261     mod_path: Option<String>,
262 ) -> Option<Markup> {
263     match desc {
264         Some(desc) => {
265             let mut buf = String::new();
266
267             if let Some(mod_path) = mod_path {
268                 if !mod_path.is_empty() {
269                     format_to!(buf, "```rust\n{}\n```\n\n", mod_path);
270                 }
271             }
272             format_to!(buf, "```rust\n{}\n```", desc);
273
274             if let Some(doc) = docs {
275                 format_to!(buf, "\n___\n\n{}", doc);
276             }
277             Some(buf.into())
278         }
279         None => docs.map(Markup::from),
280     }
281 }
282
283 fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> {
284     match def {
285         Definition::Field(f) => Some(f.parent_def(db).name(db)),
286         Definition::Local(l) => l.parent(db).name(db),
287         Definition::ModuleDef(md) => match md {
288             ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) {
289                 AssocItemContainer::Trait(t) => Some(t.name(db)),
290                 AssocItemContainer::Impl(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)),
291             },
292             ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)),
293             _ => None,
294         },
295         _ => None,
296     }
297     .map(|name| name.to_string())
298 }
299
300 fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) -> String {
301     let crate_name =
302         db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string());
303     let module_path = module
304         .path_to_root(db)
305         .into_iter()
306         .rev()
307         .flat_map(|it| it.name(db).map(|name| name.to_string()));
308     crate_name.into_iter().chain(module_path).chain(item_name).join("::")
309 }
310
311 fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
312     def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def)))
313 }
314
315 fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
316     let mod_path = definition_mod_path(db, &def);
317     return match def {
318         Definition::Macro(it) => {
319             let label = macro_label(&it.source(db)?.value);
320             from_def_source_labeled(db, it, Some(label), mod_path)
321         }
322         Definition::Field(def) => {
323             let src = def.source(db)?.value;
324             if let FieldSource::Named(it) = src {
325                 from_def_source_labeled(db, def, it.short_label(), mod_path)
326             } else {
327                 None
328             }
329         }
330         Definition::ModuleDef(it) => match it {
331             ModuleDef::Module(it) => from_def_source_labeled(
332                 db,
333                 it,
334                 match it.definition_source(db).value {
335                     ModuleSource::Module(it) => it.short_label(),
336                     ModuleSource::SourceFile(it) => it.short_label(),
337                 },
338                 mod_path,
339             ),
340             ModuleDef::Function(it) => from_def_source(db, it, mod_path),
341             ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path),
342             ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path),
343             ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path),
344             ModuleDef::Variant(it) => from_def_source(db, it, mod_path),
345             ModuleDef::Const(it) => from_def_source(db, it, mod_path),
346             ModuleDef::Static(it) => from_def_source(db, it, mod_path),
347             ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
348             ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
349             ModuleDef::BuiltinType(it) => Some(Markup::fenced_block(&it)),
350         },
351         Definition::Local(it) => Some(Markup::fenced_block(&it.ty(db).display(db))),
352         Definition::SelfType(impl_def) => {
353             impl_def.target_ty(db).as_adt().and_then(|adt| match adt {
354                 Adt::Struct(it) => from_def_source(db, it, mod_path),
355                 Adt::Union(it) => from_def_source(db, it, mod_path),
356                 Adt::Enum(it) => from_def_source(db, it, mod_path),
357             })
358         }
359         Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))),
360         Definition::LifetimeParam(it) => Some(Markup::fenced_block(&it.name(db))),
361         Definition::TypeParam(type_param) => Some(Markup::fenced_block(&type_param.display(db))),
362         Definition::ConstParam(it) => from_def_source(db, it, None),
363     };
364
365     fn from_def_source<A, D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup>
366     where
367         D: HasSource<Ast = A> + HasAttrs + Copy,
368         A: ShortLabel,
369     {
370         let short_label = def.source(db)?.value.short_label();
371         from_def_source_labeled(db, def, short_label, mod_path)
372     }
373
374     fn from_def_source_labeled<D>(
375         db: &RootDatabase,
376         def: D,
377         short_label: Option<String>,
378         mod_path: Option<String>,
379     ) -> Option<Markup>
380     where
381         D: HasAttrs,
382     {
383         let docs = def.attrs(db).docs().map(Into::into);
384         hover_markup(docs, short_label, mod_path)
385     }
386 }
387
388 fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
389     return tokens.max_by_key(priority);
390     fn priority(n: &SyntaxToken) -> usize {
391         match n.kind() {
392             IDENT | INT_NUMBER | LIFETIME_IDENT => 3,
393             T!['('] | T![')'] => 2,
394             kind if kind.is_trivia() => 0,
395             _ => 1,
396         }
397     }
398 }
399
400 #[cfg(test)]
401 mod tests {
402     use expect_test::{expect, Expect};
403     use ide_db::base_db::FileLoader;
404
405     use crate::fixture;
406
407     use super::*;
408
409     fn check_hover_no_result(ra_fixture: &str) {
410         let (analysis, position) = fixture::position(ra_fixture);
411         assert!(analysis.hover(position, true, true).unwrap().is_none());
412     }
413
414     fn check(ra_fixture: &str, expect: Expect) {
415         let (analysis, position) = fixture::position(ra_fixture);
416         let hover = analysis.hover(position, true, true).unwrap().unwrap();
417
418         let content = analysis.db.file_text(position.file_id);
419         let hovered_element = &content[hover.range];
420
421         let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
422         expect.assert_eq(&actual)
423     }
424
425     fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
426         let (analysis, position) = fixture::position(ra_fixture);
427         let hover = analysis.hover(position, false, true).unwrap().unwrap();
428
429         let content = analysis.db.file_text(position.file_id);
430         let hovered_element = &content[hover.range];
431
432         let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
433         expect.assert_eq(&actual)
434     }
435
436     fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) {
437         let (analysis, position) = fixture::position(ra_fixture);
438         let hover = analysis.hover(position, true, false).unwrap().unwrap();
439
440         let content = analysis.db.file_text(position.file_id);
441         let hovered_element = &content[hover.range];
442
443         let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
444         expect.assert_eq(&actual)
445     }
446
447     fn check_actions(ra_fixture: &str, expect: Expect) {
448         let (analysis, position) = fixture::position(ra_fixture);
449         let hover = analysis.hover(position, true, true).unwrap().unwrap();
450         expect.assert_debug_eq(&hover.info.actions)
451     }
452
453     #[test]
454     fn hover_shows_type_of_an_expression() {
455         check(
456             r#"
457 pub fn foo() -> u32 { 1 }
458
459 fn main() {
460     let foo_test = foo()$0;
461 }
462 "#,
463             expect![[r#"
464                 *foo()*
465                 ```rust
466                 u32
467                 ```
468             "#]],
469         );
470     }
471
472     #[test]
473     fn hover_remove_markdown_if_configured() {
474         check_hover_no_markdown(
475             r#"
476 pub fn foo() -> u32 { 1 }
477
478 fn main() {
479     let foo_test = foo()$0;
480 }
481 "#,
482             expect![[r#"
483                 *foo()*
484                 u32
485             "#]],
486         );
487     }
488
489     #[test]
490     fn hover_shows_long_type_of_an_expression() {
491         check(
492             r#"
493 struct Scan<A, B, C> { a: A, b: B, c: C }
494 struct Iter<I> { inner: I }
495 enum Option<T> { Some(T), None }
496
497 struct OtherStruct<T> { i: T }
498
499 fn scan<A, B, C>(a: A, b: B, c: C) -> Iter<Scan<OtherStruct<A>, B, C>> {
500     Iter { inner: Scan { a, b, c } }
501 }
502
503 fn main() {
504     let num: i32 = 55;
505     let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> Option<u32> {
506         Option::Some(*memo + value)
507     };
508     let number = 5u32;
509     let mut iter$0 = scan(OtherStruct { i: num }, closure, number);
510 }
511 "#,
512             expect![[r#"
513                 *iter*
514
515                 ```rust
516                 Iter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> Option<u32>, u32>>
517                 ```
518             "#]],
519         );
520     }
521
522     #[test]
523     fn hover_shows_fn_signature() {
524         // Single file with result
525         check(
526             r#"
527 pub fn foo() -> u32 { 1 }
528
529 fn main() { let foo_test = fo$0o(); }
530 "#,
531             expect![[r#"
532                 *foo*
533
534                 ```rust
535                 test
536                 ```
537
538                 ```rust
539                 pub fn foo() -> u32
540                 ```
541             "#]],
542         );
543
544         // Multiple candidates but results are ambiguous.
545         check(
546             r#"
547 //- /a.rs
548 pub fn foo() -> u32 { 1 }
549
550 //- /b.rs
551 pub fn foo() -> &str { "" }
552
553 //- /c.rs
554 pub fn foo(a: u32, b: u32) {}
555
556 //- /main.rs
557 mod a;
558 mod b;
559 mod c;
560
561 fn main() { let foo_test = fo$0o(); }
562         "#,
563             expect![[r#"
564                 *foo*
565                 ```rust
566                 {unknown}
567                 ```
568             "#]],
569         );
570     }
571
572     #[test]
573     fn hover_shows_fn_signature_with_type_params() {
574         check(
575             r#"
576 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { }
577
578 fn main() { let foo_test = fo$0o(); }
579         "#,
580             expect![[r#"
581                 *foo*
582
583                 ```rust
584                 test
585                 ```
586
587                 ```rust
588                 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str
589                 ```
590             "#]],
591         );
592     }
593
594     #[test]
595     fn hover_shows_fn_signature_on_fn_name() {
596         check(
597             r#"
598 pub fn foo$0(a: u32, b: u32) -> u32 {}
599
600 fn main() { }
601 "#,
602             expect![[r#"
603                 *foo*
604
605                 ```rust
606                 test
607                 ```
608
609                 ```rust
610                 pub fn foo(a: u32, b: u32) -> u32
611                 ```
612             "#]],
613         );
614     }
615
616     #[test]
617     fn hover_shows_fn_doc() {
618         check(
619             r#"
620 /// # Example
621 /// ```
622 /// # use std::path::Path;
623 /// #
624 /// foo(Path::new("hello, world!"))
625 /// ```
626 pub fn foo$0(_: &Path) {}
627
628 fn main() { }
629 "#,
630             expect![[r##"
631                 *foo*
632
633                 ```rust
634                 test
635                 ```
636
637                 ```rust
638                 pub fn foo(_: &Path)
639                 ```
640
641                 ---
642
643                 # Example
644
645                 ```
646                 # use std::path::Path;
647                 #
648                 foo(Path::new("hello, world!"))
649                 ```
650             "##]],
651         );
652     }
653
654     #[test]
655     fn hover_shows_fn_doc_attr_raw_string() {
656         check(
657             r##"
658 #[doc = r#"Raw string doc attr"#]
659 pub fn foo$0(_: &Path) {}
660
661 fn main() { }
662 "##,
663             expect![[r##"
664                 *foo*
665
666                 ```rust
667                 test
668                 ```
669
670                 ```rust
671                 pub fn foo(_: &Path)
672                 ```
673
674                 ---
675
676                 Raw string doc attr
677             "##]],
678         );
679     }
680
681     #[test]
682     fn hover_shows_struct_field_info() {
683         // Hovering over the field when instantiating
684         check(
685             r#"
686 struct Foo { field_a: u32 }
687
688 fn main() {
689     let foo = Foo { field_a$0: 0, };
690 }
691 "#,
692             expect![[r#"
693                 *field_a*
694
695                 ```rust
696                 test::Foo
697                 ```
698
699                 ```rust
700                 field_a: u32
701                 ```
702             "#]],
703         );
704
705         // Hovering over the field in the definition
706         check(
707             r#"
708 struct Foo { field_a$0: u32 }
709
710 fn main() {
711     let foo = Foo { field_a: 0 };
712 }
713 "#,
714             expect![[r#"
715                 *field_a*
716
717                 ```rust
718                 test::Foo
719                 ```
720
721                 ```rust
722                 field_a: u32
723                 ```
724             "#]],
725         );
726     }
727
728     #[test]
729     fn hover_const_static() {
730         check(
731             r#"const foo$0: u32 = 123;"#,
732             expect![[r#"
733                 *foo*
734
735                 ```rust
736                 test
737                 ```
738
739                 ```rust
740                 const foo: u32 = 123
741                 ```
742             "#]],
743         );
744         check(
745             r#"static foo$0: u32 = 456;"#,
746             expect![[r#"
747                 *foo*
748
749                 ```rust
750                 test
751                 ```
752
753                 ```rust
754                 static foo: u32
755                 ```
756             "#]],
757         );
758     }
759
760     #[test]
761     fn hover_default_generic_types() {
762         check(
763             r#"
764 struct Test<K, T = u8> { k: K, t: T }
765
766 fn main() {
767     let zz$0 = Test { t: 23u8, k: 33 };
768 }"#,
769             expect![[r#"
770                 *zz*
771
772                 ```rust
773                 Test<i32, u8>
774                 ```
775             "#]],
776         );
777     }
778
779     #[test]
780     fn hover_some() {
781         check(
782             r#"
783 enum Option<T> { Some(T) }
784 use Option::Some;
785
786 fn main() { So$0me(12); }
787 "#,
788             expect![[r#"
789                 *Some*
790
791                 ```rust
792                 test::Option
793                 ```
794
795                 ```rust
796                 Some
797                 ```
798             "#]],
799         );
800
801         check(
802             r#"
803 enum Option<T> { Some(T) }
804 use Option::Some;
805
806 fn main() { let b$0ar = Some(12); }
807 "#,
808             expect![[r#"
809                 *bar*
810
811                 ```rust
812                 Option<i32>
813                 ```
814             "#]],
815         );
816     }
817
818     #[test]
819     fn hover_enum_variant() {
820         check(
821             r#"
822 enum Option<T> {
823     /// The None variant
824     Non$0e
825 }
826 "#,
827             expect![[r#"
828                 *None*
829
830                 ```rust
831                 test::Option
832                 ```
833
834                 ```rust
835                 None
836                 ```
837
838                 ---
839
840                 The None variant
841             "#]],
842         );
843
844         check(
845             r#"
846 enum Option<T> {
847     /// The Some variant
848     Some(T)
849 }
850 fn main() {
851     let s = Option::Som$0e(12);
852 }
853 "#,
854             expect![[r#"
855                 *Some*
856
857                 ```rust
858                 test::Option
859                 ```
860
861                 ```rust
862                 Some
863                 ```
864
865                 ---
866
867                 The Some variant
868             "#]],
869         );
870     }
871
872     #[test]
873     fn hover_for_local_variable() {
874         check(
875             r#"fn func(foo: i32) { fo$0o; }"#,
876             expect![[r#"
877                 *foo*
878
879                 ```rust
880                 i32
881                 ```
882             "#]],
883         )
884     }
885
886     #[test]
887     fn hover_for_local_variable_pat() {
888         check(
889             r#"fn func(fo$0o: i32) {}"#,
890             expect![[r#"
891                 *foo*
892
893                 ```rust
894                 i32
895                 ```
896             "#]],
897         )
898     }
899
900     #[test]
901     fn hover_local_var_edge() {
902         check(
903             r#"fn func(foo: i32) { if true { $0foo; }; }"#,
904             expect![[r#"
905                 *foo*
906
907                 ```rust
908                 i32
909                 ```
910             "#]],
911         )
912     }
913
914     #[test]
915     fn hover_for_param_edge() {
916         check(
917             r#"fn func($0foo: i32) {}"#,
918             expect![[r#"
919                 *foo*
920
921                 ```rust
922                 i32
923                 ```
924             "#]],
925         )
926     }
927
928     #[test]
929     fn hover_for_param_with_multiple_traits() {
930         check(
931             r#"trait Deref {
932                 type Target: ?Sized;
933             }
934             trait DerefMut {
935                 type Target: ?Sized;
936             }
937             fn f(_x$0: impl Deref<Target=u8> + DerefMut<Target=u8>) {}"#,
938             expect![[r#"
939                 *_x*
940
941                 ```rust
942                 impl Deref<Target = u8> + DerefMut<Target = u8>
943                 ```
944             "#]],
945         )
946     }
947
948     #[test]
949     fn test_hover_infer_associated_method_result() {
950         check(
951             r#"
952 struct Thing { x: u32 }
953
954 impl Thing {
955     fn new() -> Thing { Thing { x: 0 } }
956 }
957
958 fn main() { let foo_$0test = Thing::new(); }
959             "#,
960             expect![[r#"
961                 *foo_test*
962
963                 ```rust
964                 Thing
965                 ```
966             "#]],
967         )
968     }
969
970     #[test]
971     fn test_hover_infer_associated_method_exact() {
972         check(
973             r#"
974 mod wrapper {
975     struct Thing { x: u32 }
976
977     impl Thing {
978         fn new() -> Thing { Thing { x: 0 } }
979     }
980 }
981
982 fn main() { let foo_test = wrapper::Thing::new$0(); }
983 "#,
984             expect![[r#"
985                 *new*
986
987                 ```rust
988                 test::wrapper::Thing
989                 ```
990
991                 ```rust
992                 fn new() -> Thing
993                 ```
994             "#]],
995         )
996     }
997
998     #[test]
999     fn test_hover_infer_associated_const_in_pattern() {
1000         check(
1001             r#"
1002 struct X;
1003 impl X {
1004     const C: u32 = 1;
1005 }
1006
1007 fn main() {
1008     match 1 {
1009         X::C$0 => {},
1010         2 => {},
1011         _ => {}
1012     };
1013 }
1014 "#,
1015             expect![[r#"
1016                 *C*
1017
1018                 ```rust
1019                 test
1020                 ```
1021
1022                 ```rust
1023                 const C: u32 = 1
1024                 ```
1025             "#]],
1026         )
1027     }
1028
1029     #[test]
1030     fn test_hover_self() {
1031         check(
1032             r#"
1033 struct Thing { x: u32 }
1034 impl Thing {
1035     fn new() -> Self { Self$0 { x: 0 } }
1036 }
1037 "#,
1038             expect![[r#"
1039                 *Self*
1040
1041                 ```rust
1042                 test
1043                 ```
1044
1045                 ```rust
1046                 struct Thing
1047                 ```
1048             "#]],
1049         );
1050         check(
1051             r#"
1052 struct Thing { x: u32 }
1053 impl Thing {
1054     fn new() -> Self$0 { Self { x: 0 } }
1055 }
1056 "#,
1057             expect![[r#"
1058                 *Self*
1059
1060                 ```rust
1061                 test
1062                 ```
1063
1064                 ```rust
1065                 struct Thing
1066                 ```
1067             "#]],
1068         );
1069         check(
1070             r#"
1071 enum Thing { A }
1072 impl Thing {
1073     pub fn new() -> Self$0 { Thing::A }
1074 }
1075 "#,
1076             expect![[r#"
1077                 *Self*
1078
1079                 ```rust
1080                 test
1081                 ```
1082
1083                 ```rust
1084                 enum Thing
1085                 ```
1086             "#]],
1087         );
1088         check(
1089             r#"
1090         enum Thing { A }
1091         impl Thing {
1092             pub fn thing(a: Self$0) {}
1093         }
1094         "#,
1095             expect![[r#"
1096                 *Self*
1097
1098                 ```rust
1099                 test
1100                 ```
1101
1102                 ```rust
1103                 enum Thing
1104                 ```
1105             "#]],
1106         );
1107     }
1108
1109     #[test]
1110     fn test_hover_shadowing_pat() {
1111         check(
1112             r#"
1113 fn x() {}
1114
1115 fn y() {
1116     let x = 0i32;
1117     x$0;
1118 }
1119 "#,
1120             expect![[r#"
1121                 *x*
1122
1123                 ```rust
1124                 i32
1125                 ```
1126             "#]],
1127         )
1128     }
1129
1130     #[test]
1131     fn test_hover_macro_invocation() {
1132         check(
1133             r#"
1134 macro_rules! foo { () => {} }
1135
1136 fn f() { fo$0o!(); }
1137 "#,
1138             expect![[r#"
1139                 *foo*
1140
1141                 ```rust
1142                 test
1143                 ```
1144
1145                 ```rust
1146                 macro_rules! foo
1147                 ```
1148             "#]],
1149         )
1150     }
1151
1152     #[test]
1153     fn test_hover_tuple_field() {
1154         check(
1155             r#"struct TS(String, i32$0);"#,
1156             expect![[r#"
1157                 *i32*
1158
1159                 ```rust
1160                 i32
1161                 ```
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$0o(); }
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$0r); }
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$0r); }
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($0)] ); }
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$0acks", &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$0r());
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$0lo {}", 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$0o(); }
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$0() {}"#,
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$0() {}"#,
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$0() {}"#,
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$0() {}",
1379             expect![[r#"
1380                 [
1381                     Implementation(
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$0d;
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$0c;
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$0y::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$0r; }
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$0r; }
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$0r; }
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$0ar
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$0ar
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$0ld: ()
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$0ar
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$0ar
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$0ar
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$0ar
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$0ar
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$0ar
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$0ar
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$0ar
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$0ar
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$0ar
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$0 { 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$0: 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$0o() {}
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$0o(); }
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$0o(); }
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$0() {}"#,
2091             expect![[r#"
2092                 [
2093                     Implementation(
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$0() {}",
2110             expect![[r#"
2111                 [
2112                     Implementation(
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$0() {}"#,
2129             expect![[r#"
2130                 [
2131                     Implementation(
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$0() { A, B }",
2148             expect![[r#"
2149                 [
2150                     Implementation(
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_self_has_impl_action() {
2165         check_actions(
2166             r#"struct foo where Self$0:;"#,
2167             expect![[r#"
2168                 [
2169                     Implementation(
2170                         FilePosition {
2171                             file_id: FileId(
2172                                 0,
2173                             ),
2174                             offset: 7,
2175                         },
2176                     ),
2177                 ]
2178             "#]],
2179         );
2180     }
2181
2182     #[test]
2183     fn test_hover_test_has_action() {
2184         check_actions(
2185             r#"
2186 #[test]
2187 fn foo_$0test() {}
2188 "#,
2189             expect![[r#"
2190                 [
2191                     Runnable(
2192                         Runnable {
2193                             nav: NavigationTarget {
2194                                 file_id: FileId(
2195                                     0,
2196                                 ),
2197                                 full_range: 0..24,
2198                                 focus_range: 11..19,
2199                                 name: "foo_test",
2200                                 kind: Function,
2201                             },
2202                             kind: Test {
2203                                 test_id: Path(
2204                                     "foo_test",
2205                                 ),
2206                                 attr: TestAttr {
2207                                     ignore: false,
2208                                 },
2209                             },
2210                             cfg: None,
2211                         },
2212                     ),
2213                 ]
2214             "#]],
2215         );
2216     }
2217
2218     #[test]
2219     fn test_hover_test_mod_has_action() {
2220         check_actions(
2221             r#"
2222 mod tests$0 {
2223     #[test]
2224     fn foo_test() {}
2225 }
2226 "#,
2227             expect![[r#"
2228                 [
2229                     Runnable(
2230                         Runnable {
2231                             nav: NavigationTarget {
2232                                 file_id: FileId(
2233                                     0,
2234                                 ),
2235                                 full_range: 0..46,
2236                                 focus_range: 4..9,
2237                                 name: "tests",
2238                                 kind: Module,
2239                             },
2240                             kind: TestMod {
2241                                 path: "tests",
2242                             },
2243                             cfg: None,
2244                         },
2245                     ),
2246                 ]
2247             "#]],
2248         );
2249     }
2250
2251     #[test]
2252     fn test_hover_struct_has_goto_type_action() {
2253         check_actions(
2254             r#"
2255 struct S{ f1: u32 }
2256
2257 fn main() { let s$0t = S{ f1:0 }; }
2258             "#,
2259             expect![[r#"
2260                 [
2261                     GoToType(
2262                         [
2263                             HoverGotoTypeData {
2264                                 mod_path: "test::S",
2265                                 nav: NavigationTarget {
2266                                     file_id: FileId(
2267                                         0,
2268                                     ),
2269                                     full_range: 0..19,
2270                                     focus_range: 7..8,
2271                                     name: "S",
2272                                     kind: Struct,
2273                                     description: "struct S",
2274                                 },
2275                             },
2276                         ],
2277                     ),
2278                 ]
2279             "#]],
2280         );
2281     }
2282
2283     #[test]
2284     fn test_hover_generic_struct_has_goto_type_actions() {
2285         check_actions(
2286             r#"
2287 struct Arg(u32);
2288 struct S<T>{ f1: T }
2289
2290 fn main() { let s$0t = S{ f1:Arg(0) }; }
2291 "#,
2292             expect![[r#"
2293                 [
2294                     GoToType(
2295                         [
2296                             HoverGotoTypeData {
2297                                 mod_path: "test::S",
2298                                 nav: NavigationTarget {
2299                                     file_id: FileId(
2300                                         0,
2301                                     ),
2302                                     full_range: 17..37,
2303                                     focus_range: 24..25,
2304                                     name: "S",
2305                                     kind: Struct,
2306                                     description: "struct S",
2307                                 },
2308                             },
2309                             HoverGotoTypeData {
2310                                 mod_path: "test::Arg",
2311                                 nav: NavigationTarget {
2312                                     file_id: FileId(
2313                                         0,
2314                                     ),
2315                                     full_range: 0..16,
2316                                     focus_range: 7..10,
2317                                     name: "Arg",
2318                                     kind: Struct,
2319                                     description: "struct Arg",
2320                                 },
2321                             },
2322                         ],
2323                     ),
2324                 ]
2325             "#]],
2326         );
2327     }
2328
2329     #[test]
2330     fn test_hover_generic_struct_has_flattened_goto_type_actions() {
2331         check_actions(
2332             r#"
2333 struct Arg(u32);
2334 struct S<T>{ f1: T }
2335
2336 fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
2337             "#,
2338             expect![[r#"
2339                 [
2340                     GoToType(
2341                         [
2342                             HoverGotoTypeData {
2343                                 mod_path: "test::S",
2344                                 nav: NavigationTarget {
2345                                     file_id: FileId(
2346                                         0,
2347                                     ),
2348                                     full_range: 17..37,
2349                                     focus_range: 24..25,
2350                                     name: "S",
2351                                     kind: Struct,
2352                                     description: "struct S",
2353                                 },
2354                             },
2355                             HoverGotoTypeData {
2356                                 mod_path: "test::Arg",
2357                                 nav: NavigationTarget {
2358                                     file_id: FileId(
2359                                         0,
2360                                     ),
2361                                     full_range: 0..16,
2362                                     focus_range: 7..10,
2363                                     name: "Arg",
2364                                     kind: Struct,
2365                                     description: "struct Arg",
2366                                 },
2367                             },
2368                         ],
2369                     ),
2370                 ]
2371             "#]],
2372         );
2373     }
2374
2375     #[test]
2376     fn test_hover_tuple_has_goto_type_actions() {
2377         check_actions(
2378             r#"
2379 struct A(u32);
2380 struct B(u32);
2381 mod M {
2382     pub struct C(u32);
2383 }
2384
2385 fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
2386 "#,
2387             expect![[r#"
2388                 [
2389                     GoToType(
2390                         [
2391                             HoverGotoTypeData {
2392                                 mod_path: "test::A",
2393                                 nav: NavigationTarget {
2394                                     file_id: FileId(
2395                                         0,
2396                                     ),
2397                                     full_range: 0..14,
2398                                     focus_range: 7..8,
2399                                     name: "A",
2400                                     kind: Struct,
2401                                     description: "struct A",
2402                                 },
2403                             },
2404                             HoverGotoTypeData {
2405                                 mod_path: "test::B",
2406                                 nav: NavigationTarget {
2407                                     file_id: FileId(
2408                                         0,
2409                                     ),
2410                                     full_range: 15..29,
2411                                     focus_range: 22..23,
2412                                     name: "B",
2413                                     kind: Struct,
2414                                     description: "struct B",
2415                                 },
2416                             },
2417                             HoverGotoTypeData {
2418                                 mod_path: "test::M::C",
2419                                 nav: NavigationTarget {
2420                                     file_id: FileId(
2421                                         0,
2422                                     ),
2423                                     full_range: 42..60,
2424                                     focus_range: 53..54,
2425                                     name: "C",
2426                                     kind: Struct,
2427                                     description: "pub struct C",
2428                                 },
2429                             },
2430                         ],
2431                     ),
2432                 ]
2433             "#]],
2434         );
2435     }
2436
2437     #[test]
2438     fn test_hover_return_impl_trait_has_goto_type_action() {
2439         check_actions(
2440             r#"
2441 trait Foo {}
2442 fn foo() -> impl Foo {}
2443
2444 fn main() { let s$0t = foo(); }
2445 "#,
2446             expect![[r#"
2447                 [
2448                     GoToType(
2449                         [
2450                             HoverGotoTypeData {
2451                                 mod_path: "test::Foo",
2452                                 nav: NavigationTarget {
2453                                     file_id: FileId(
2454                                         0,
2455                                     ),
2456                                     full_range: 0..12,
2457                                     focus_range: 6..9,
2458                                     name: "Foo",
2459                                     kind: Trait,
2460                                     description: "trait Foo",
2461                                 },
2462                             },
2463                         ],
2464                     ),
2465                 ]
2466             "#]],
2467         );
2468     }
2469
2470     #[test]
2471     fn test_hover_generic_return_impl_trait_has_goto_type_action() {
2472         check_actions(
2473             r#"
2474 trait Foo<T> {}
2475 struct S;
2476 fn foo() -> impl Foo<S> {}
2477
2478 fn main() { let s$0t = foo(); }
2479 "#,
2480             expect![[r#"
2481                 [
2482                     GoToType(
2483                         [
2484                             HoverGotoTypeData {
2485                                 mod_path: "test::Foo",
2486                                 nav: NavigationTarget {
2487                                     file_id: FileId(
2488                                         0,
2489                                     ),
2490                                     full_range: 0..15,
2491                                     focus_range: 6..9,
2492                                     name: "Foo",
2493                                     kind: Trait,
2494                                     description: "trait Foo",
2495                                 },
2496                             },
2497                             HoverGotoTypeData {
2498                                 mod_path: "test::S",
2499                                 nav: NavigationTarget {
2500                                     file_id: FileId(
2501                                         0,
2502                                     ),
2503                                     full_range: 16..25,
2504                                     focus_range: 23..24,
2505                                     name: "S",
2506                                     kind: Struct,
2507                                     description: "struct S",
2508                                 },
2509                             },
2510                         ],
2511                     ),
2512                 ]
2513             "#]],
2514         );
2515     }
2516
2517     #[test]
2518     fn test_hover_return_impl_traits_has_goto_type_action() {
2519         check_actions(
2520             r#"
2521 trait Foo {}
2522 trait Bar {}
2523 fn foo() -> impl Foo + Bar {}
2524
2525 fn main() { let s$0t = foo(); }
2526             "#,
2527             expect![[r#"
2528                 [
2529                     GoToType(
2530                         [
2531                             HoverGotoTypeData {
2532                                 mod_path: "test::Foo",
2533                                 nav: NavigationTarget {
2534                                     file_id: FileId(
2535                                         0,
2536                                     ),
2537                                     full_range: 0..12,
2538                                     focus_range: 6..9,
2539                                     name: "Foo",
2540                                     kind: Trait,
2541                                     description: "trait Foo",
2542                                 },
2543                             },
2544                             HoverGotoTypeData {
2545                                 mod_path: "test::Bar",
2546                                 nav: NavigationTarget {
2547                                     file_id: FileId(
2548                                         0,
2549                                     ),
2550                                     full_range: 13..25,
2551                                     focus_range: 19..22,
2552                                     name: "Bar",
2553                                     kind: Trait,
2554                                     description: "trait Bar",
2555                                 },
2556                             },
2557                         ],
2558                     ),
2559                 ]
2560             "#]],
2561         );
2562     }
2563
2564     #[test]
2565     fn test_hover_generic_return_impl_traits_has_goto_type_action() {
2566         check_actions(
2567             r#"
2568 trait Foo<T> {}
2569 trait Bar<T> {}
2570 struct S1 {}
2571 struct S2 {}
2572
2573 fn foo() -> impl Foo<S1> + Bar<S2> {}
2574
2575 fn main() { let s$0t = foo(); }
2576 "#,
2577             expect![[r#"
2578                 [
2579                     GoToType(
2580                         [
2581                             HoverGotoTypeData {
2582                                 mod_path: "test::Foo",
2583                                 nav: NavigationTarget {
2584                                     file_id: FileId(
2585                                         0,
2586                                     ),
2587                                     full_range: 0..15,
2588                                     focus_range: 6..9,
2589                                     name: "Foo",
2590                                     kind: Trait,
2591                                     description: "trait Foo",
2592                                 },
2593                             },
2594                             HoverGotoTypeData {
2595                                 mod_path: "test::Bar",
2596                                 nav: NavigationTarget {
2597                                     file_id: FileId(
2598                                         0,
2599                                     ),
2600                                     full_range: 16..31,
2601                                     focus_range: 22..25,
2602                                     name: "Bar",
2603                                     kind: Trait,
2604                                     description: "trait Bar",
2605                                 },
2606                             },
2607                             HoverGotoTypeData {
2608                                 mod_path: "test::S1",
2609                                 nav: NavigationTarget {
2610                                     file_id: FileId(
2611                                         0,
2612                                     ),
2613                                     full_range: 32..44,
2614                                     focus_range: 39..41,
2615                                     name: "S1",
2616                                     kind: Struct,
2617                                     description: "struct S1",
2618                                 },
2619                             },
2620                             HoverGotoTypeData {
2621                                 mod_path: "test::S2",
2622                                 nav: NavigationTarget {
2623                                     file_id: FileId(
2624                                         0,
2625                                     ),
2626                                     full_range: 45..57,
2627                                     focus_range: 52..54,
2628                                     name: "S2",
2629                                     kind: Struct,
2630                                     description: "struct S2",
2631                                 },
2632                             },
2633                         ],
2634                     ),
2635                 ]
2636             "#]],
2637         );
2638     }
2639
2640     #[test]
2641     fn test_hover_arg_impl_trait_has_goto_type_action() {
2642         check_actions(
2643             r#"
2644 trait Foo {}
2645 fn foo(ar$0g: &impl Foo) {}
2646 "#,
2647             expect![[r#"
2648                 [
2649                     GoToType(
2650                         [
2651                             HoverGotoTypeData {
2652                                 mod_path: "test::Foo",
2653                                 nav: NavigationTarget {
2654                                     file_id: FileId(
2655                                         0,
2656                                     ),
2657                                     full_range: 0..12,
2658                                     focus_range: 6..9,
2659                                     name: "Foo",
2660                                     kind: Trait,
2661                                     description: "trait Foo",
2662                                 },
2663                             },
2664                         ],
2665                     ),
2666                 ]
2667             "#]],
2668         );
2669     }
2670
2671     #[test]
2672     fn test_hover_arg_impl_traits_has_goto_type_action() {
2673         check_actions(
2674             r#"
2675 trait Foo {}
2676 trait Bar<T> {}
2677 struct S{}
2678
2679 fn foo(ar$0g: &impl Foo + Bar<S>) {}
2680 "#,
2681             expect![[r#"
2682                 [
2683                     GoToType(
2684                         [
2685                             HoverGotoTypeData {
2686                                 mod_path: "test::Foo",
2687                                 nav: NavigationTarget {
2688                                     file_id: FileId(
2689                                         0,
2690                                     ),
2691                                     full_range: 0..12,
2692                                     focus_range: 6..9,
2693                                     name: "Foo",
2694                                     kind: Trait,
2695                                     description: "trait Foo",
2696                                 },
2697                             },
2698                             HoverGotoTypeData {
2699                                 mod_path: "test::Bar",
2700                                 nav: NavigationTarget {
2701                                     file_id: FileId(
2702                                         0,
2703                                     ),
2704                                     full_range: 13..28,
2705                                     focus_range: 19..22,
2706                                     name: "Bar",
2707                                     kind: Trait,
2708                                     description: "trait Bar",
2709                                 },
2710                             },
2711                             HoverGotoTypeData {
2712                                 mod_path: "test::S",
2713                                 nav: NavigationTarget {
2714                                     file_id: FileId(
2715                                         0,
2716                                     ),
2717                                     full_range: 29..39,
2718                                     focus_range: 36..37,
2719                                     name: "S",
2720                                     kind: Struct,
2721                                     description: "struct S",
2722                                 },
2723                             },
2724                         ],
2725                     ),
2726                 ]
2727             "#]],
2728         );
2729     }
2730
2731     #[test]
2732     fn test_hover_async_block_impl_trait_has_goto_type_action() {
2733         check_actions(
2734             r#"
2735 struct S;
2736 fn foo() {
2737     let fo$0o = async { S };
2738 }
2739
2740 #[prelude_import] use future::*;
2741 mod future {
2742     #[lang = "future_trait"]
2743     pub trait Future { type Output; }
2744 }
2745 "#,
2746             expect![[r#"
2747                 [
2748                     GoToType(
2749                         [
2750                             HoverGotoTypeData {
2751                                 mod_path: "test::future::Future",
2752                                 nav: NavigationTarget {
2753                                     file_id: FileId(
2754                                         0,
2755                                     ),
2756                                     full_range: 101..163,
2757                                     focus_range: 140..146,
2758                                     name: "Future",
2759                                     kind: Trait,
2760                                     description: "pub trait Future",
2761                                 },
2762                             },
2763                             HoverGotoTypeData {
2764                                 mod_path: "test::S",
2765                                 nav: NavigationTarget {
2766                                     file_id: FileId(
2767                                         0,
2768                                     ),
2769                                     full_range: 0..9,
2770                                     focus_range: 7..8,
2771                                     name: "S",
2772                                     kind: Struct,
2773                                     description: "struct S",
2774                                 },
2775                             },
2776                         ],
2777                     ),
2778                 ]
2779             "#]],
2780         );
2781     }
2782
2783     #[test]
2784     fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
2785         check_actions(
2786             r#"
2787 trait Foo<T> {}
2788 struct S {}
2789 fn foo(ar$0g: &impl Foo<S>) {}
2790 "#,
2791             expect![[r#"
2792                 [
2793                     GoToType(
2794                         [
2795                             HoverGotoTypeData {
2796                                 mod_path: "test::Foo",
2797                                 nav: NavigationTarget {
2798                                     file_id: FileId(
2799                                         0,
2800                                     ),
2801                                     full_range: 0..15,
2802                                     focus_range: 6..9,
2803                                     name: "Foo",
2804                                     kind: Trait,
2805                                     description: "trait Foo",
2806                                 },
2807                             },
2808                             HoverGotoTypeData {
2809                                 mod_path: "test::S",
2810                                 nav: NavigationTarget {
2811                                     file_id: FileId(
2812                                         0,
2813                                     ),
2814                                     full_range: 16..27,
2815                                     focus_range: 23..24,
2816                                     name: "S",
2817                                     kind: Struct,
2818                                     description: "struct S",
2819                                 },
2820                             },
2821                         ],
2822                     ),
2823                 ]
2824             "#]],
2825         );
2826     }
2827
2828     #[test]
2829     fn test_hover_dyn_return_has_goto_type_action() {
2830         check_actions(
2831             r#"
2832 trait Foo {}
2833 struct S;
2834 impl Foo for S {}
2835
2836 struct B<T>{}
2837 fn foo() -> B<dyn Foo> {}
2838
2839 fn main() { let s$0t = foo(); }
2840 "#,
2841             expect![[r#"
2842                 [
2843                     GoToType(
2844                         [
2845                             HoverGotoTypeData {
2846                                 mod_path: "test::B",
2847                                 nav: NavigationTarget {
2848                                     file_id: FileId(
2849                                         0,
2850                                     ),
2851                                     full_range: 42..55,
2852                                     focus_range: 49..50,
2853                                     name: "B",
2854                                     kind: Struct,
2855                                     description: "struct B",
2856                                 },
2857                             },
2858                             HoverGotoTypeData {
2859                                 mod_path: "test::Foo",
2860                                 nav: NavigationTarget {
2861                                     file_id: FileId(
2862                                         0,
2863                                     ),
2864                                     full_range: 0..12,
2865                                     focus_range: 6..9,
2866                                     name: "Foo",
2867                                     kind: Trait,
2868                                     description: "trait Foo",
2869                                 },
2870                             },
2871                         ],
2872                     ),
2873                 ]
2874             "#]],
2875         );
2876     }
2877
2878     #[test]
2879     fn test_hover_dyn_arg_has_goto_type_action() {
2880         check_actions(
2881             r#"
2882 trait Foo {}
2883 fn foo(ar$0g: &dyn Foo) {}
2884 "#,
2885             expect![[r#"
2886                 [
2887                     GoToType(
2888                         [
2889                             HoverGotoTypeData {
2890                                 mod_path: "test::Foo",
2891                                 nav: NavigationTarget {
2892                                     file_id: FileId(
2893                                         0,
2894                                     ),
2895                                     full_range: 0..12,
2896                                     focus_range: 6..9,
2897                                     name: "Foo",
2898                                     kind: Trait,
2899                                     description: "trait Foo",
2900                                 },
2901                             },
2902                         ],
2903                     ),
2904                 ]
2905             "#]],
2906         );
2907     }
2908
2909     #[test]
2910     fn test_hover_generic_dyn_arg_has_goto_type_action() {
2911         check_actions(
2912             r#"
2913 trait Foo<T> {}
2914 struct S {}
2915 fn foo(ar$0g: &dyn Foo<S>) {}
2916 "#,
2917             expect![[r#"
2918                 [
2919                     GoToType(
2920                         [
2921                             HoverGotoTypeData {
2922                                 mod_path: "test::Foo",
2923                                 nav: NavigationTarget {
2924                                     file_id: FileId(
2925                                         0,
2926                                     ),
2927                                     full_range: 0..15,
2928                                     focus_range: 6..9,
2929                                     name: "Foo",
2930                                     kind: Trait,
2931                                     description: "trait Foo",
2932                                 },
2933                             },
2934                             HoverGotoTypeData {
2935                                 mod_path: "test::S",
2936                                 nav: NavigationTarget {
2937                                     file_id: FileId(
2938                                         0,
2939                                     ),
2940                                     full_range: 16..27,
2941                                     focus_range: 23..24,
2942                                     name: "S",
2943                                     kind: Struct,
2944                                     description: "struct S",
2945                                 },
2946                             },
2947                         ],
2948                     ),
2949                 ]
2950             "#]],
2951         );
2952     }
2953
2954     #[test]
2955     fn test_hover_goto_type_action_links_order() {
2956         check_actions(
2957             r#"
2958 trait ImplTrait<T> {}
2959 trait DynTrait<T> {}
2960 struct B<T> {}
2961 struct S {}
2962
2963 fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
2964             "#,
2965             expect![[r#"
2966                 [
2967                     GoToType(
2968                         [
2969                             HoverGotoTypeData {
2970                                 mod_path: "test::ImplTrait",
2971                                 nav: NavigationTarget {
2972                                     file_id: FileId(
2973                                         0,
2974                                     ),
2975                                     full_range: 0..21,
2976                                     focus_range: 6..15,
2977                                     name: "ImplTrait",
2978                                     kind: Trait,
2979                                     description: "trait ImplTrait",
2980                                 },
2981                             },
2982                             HoverGotoTypeData {
2983                                 mod_path: "test::B",
2984                                 nav: NavigationTarget {
2985                                     file_id: FileId(
2986                                         0,
2987                                     ),
2988                                     full_range: 43..57,
2989                                     focus_range: 50..51,
2990                                     name: "B",
2991                                     kind: Struct,
2992                                     description: "struct B",
2993                                 },
2994                             },
2995                             HoverGotoTypeData {
2996                                 mod_path: "test::DynTrait",
2997                                 nav: NavigationTarget {
2998                                     file_id: FileId(
2999                                         0,
3000                                     ),
3001                                     full_range: 22..42,
3002                                     focus_range: 28..36,
3003                                     name: "DynTrait",
3004                                     kind: Trait,
3005                                     description: "trait DynTrait",
3006                                 },
3007                             },
3008                             HoverGotoTypeData {
3009                                 mod_path: "test::S",
3010                                 nav: NavigationTarget {
3011                                     file_id: FileId(
3012                                         0,
3013                                     ),
3014                                     full_range: 58..69,
3015                                     focus_range: 65..66,
3016                                     name: "S",
3017                                     kind: Struct,
3018                                     description: "struct S",
3019                                 },
3020                             },
3021                         ],
3022                     ),
3023                 ]
3024             "#]],
3025         );
3026     }
3027
3028     #[test]
3029     fn test_hover_associated_type_has_goto_type_action() {
3030         check_actions(
3031             r#"
3032 trait Foo {
3033     type Item;
3034     fn get(self) -> Self::Item {}
3035 }
3036
3037 struct Bar{}
3038 struct S{}
3039
3040 impl Foo for S { type Item = Bar; }
3041
3042 fn test() -> impl Foo { S {} }
3043
3044 fn main() { let s$0t = test().get(); }
3045 "#,
3046             expect![[r#"
3047                 [
3048                     GoToType(
3049                         [
3050                             HoverGotoTypeData {
3051                                 mod_path: "test::Foo",
3052                                 nav: NavigationTarget {
3053                                     file_id: FileId(
3054                                         0,
3055                                     ),
3056                                     full_range: 0..62,
3057                                     focus_range: 6..9,
3058                                     name: "Foo",
3059                                     kind: Trait,
3060                                     description: "trait Foo",
3061                                 },
3062                             },
3063                         ],
3064                     ),
3065                 ]
3066             "#]],
3067         );
3068     }
3069
3070     #[test]
3071     fn test_hover_const_param_has_goto_type_action() {
3072         check_actions(
3073             r#"
3074 struct Bar;
3075 struct Foo<const BAR: Bar>;
3076
3077 impl<const BAR: Bar> Foo<BAR$0> {}
3078 "#,
3079             expect![[r#"
3080                 [
3081                     GoToType(
3082                         [
3083                             HoverGotoTypeData {
3084                                 mod_path: "test::Bar",
3085                                 nav: NavigationTarget {
3086                                     file_id: FileId(
3087                                         0,
3088                                     ),
3089                                     full_range: 0..11,
3090                                     focus_range: 7..10,
3091                                     name: "Bar",
3092                                     kind: Struct,
3093                                     description: "struct Bar",
3094                                 },
3095                             },
3096                         ],
3097                     ),
3098                 ]
3099             "#]],
3100         );
3101     }
3102
3103     #[test]
3104     fn test_hover_type_param_has_goto_type_action() {
3105         check_actions(
3106             r#"
3107 trait Foo {}
3108
3109 fn foo<T: Foo>(t: T$0){}
3110 "#,
3111             expect![[r#"
3112                 [
3113                     GoToType(
3114                         [
3115                             HoverGotoTypeData {
3116                                 mod_path: "test::Foo",
3117                                 nav: NavigationTarget {
3118                                     file_id: FileId(
3119                                         0,
3120                                     ),
3121                                     full_range: 0..12,
3122                                     focus_range: 6..9,
3123                                     name: "Foo",
3124                                     kind: Trait,
3125                                     description: "trait Foo",
3126                                 },
3127                             },
3128                         ],
3129                     ),
3130                 ]
3131             "#]],
3132         );
3133     }
3134
3135     #[test]
3136     fn hover_displays_normalized_crate_names() {
3137         check(
3138             r#"
3139 //- /lib.rs crate:name-with-dashes
3140 pub mod wrapper {
3141     pub struct Thing { x: u32 }
3142
3143     impl Thing {
3144         pub fn new() -> Thing { Thing { x: 0 } }
3145     }
3146 }
3147
3148 //- /main.rs crate:main deps:name-with-dashes
3149 fn main() { let foo_test = name_with_dashes::wrapper::Thing::new$0(); }
3150 "#,
3151             expect![[r#"
3152             *new*
3153
3154             ```rust
3155             name_with_dashes::wrapper::Thing
3156             ```
3157
3158             ```rust
3159             pub fn new() -> Thing
3160             ```
3161             "#]],
3162         )
3163     }
3164
3165     #[test]
3166     fn hover_field_pat_shorthand_ref_match_ergonomics() {
3167         check(
3168             r#"
3169 struct S {
3170     f: i32,
3171 }
3172
3173 fn main() {
3174     let s = S { f: 0 };
3175     let S { f$0 } = &s;
3176 }
3177 "#,
3178             expect![[r#"
3179                 *f*
3180
3181                 ```rust
3182                 &i32
3183                 ```
3184             "#]],
3185         );
3186     }
3187
3188     #[test]
3189     fn hover_self_param_shows_type() {
3190         check(
3191             r#"
3192 struct Foo {}
3193 impl Foo {
3194     fn bar(&sel$0f) {}
3195 }
3196 "#,
3197             expect![[r#"
3198                 *&self*
3199                 ```rust
3200                 &Foo
3201                 ```
3202             "#]],
3203         );
3204     }
3205
3206     #[test]
3207     fn hover_self_param_shows_type_for_arbitrary_self_type() {
3208         check(
3209             r#"
3210 struct Arc<T>(T);
3211 struct Foo {}
3212 impl Foo {
3213     fn bar(sel$0f: Arc<Foo>) {}
3214 }
3215 "#,
3216             expect![[r#"
3217                 *self: Arc<Foo>*
3218                 ```rust
3219                 Arc<Foo>
3220                 ```
3221             "#]],
3222         );
3223     }
3224
3225     #[test]
3226     fn hover_doc_outer_inner() {
3227         check(
3228             r#"
3229 /// Be quick;
3230 mod Foo$0 {
3231     //! time is mana
3232
3233     /// This comment belongs to the function
3234     fn foo() {}
3235 }
3236 "#,
3237             expect![[r#"
3238                 *Foo*
3239
3240                 ```rust
3241                 test
3242                 ```
3243
3244                 ```rust
3245                 mod Foo
3246                 ```
3247
3248                 ---
3249
3250                 Be quick;
3251                 time is mana
3252             "#]],
3253         );
3254     }
3255
3256     #[test]
3257     fn hover_doc_outer_inner_attribue() {
3258         check(
3259             r#"
3260 #[doc = "Be quick;"]
3261 mod Foo$0 {
3262     #![doc = "time is mana"]
3263
3264     #[doc = "This comment belongs to the function"]
3265     fn foo() {}
3266 }
3267 "#,
3268             expect![[r#"
3269                 *Foo*
3270
3271                 ```rust
3272                 test
3273                 ```
3274
3275                 ```rust
3276                 mod Foo
3277                 ```
3278
3279                 ---
3280
3281                 Be quick;
3282                 time is mana
3283             "#]],
3284         );
3285     }
3286
3287     #[test]
3288     fn hover_comments_dont_highlight_parent() {
3289         check_hover_no_result(
3290             r#"
3291 fn no_hover() {
3292     // no$0hover
3293 }
3294 "#,
3295         );
3296     }
3297
3298     #[test]
3299     fn hover_label() {
3300         check(
3301             r#"
3302 fn foo() {
3303     'label$0: loop {}
3304 }
3305 "#,
3306             expect![[r#"
3307             *'label*
3308
3309             ```rust
3310             'label
3311             ```
3312             "#]],
3313         );
3314     }
3315
3316     #[test]
3317     fn hover_lifetime() {
3318         check(
3319             r#"fn foo<'lifetime>(_: &'lifetime$0 ()) {}"#,
3320             expect![[r#"
3321             *'lifetime*
3322
3323             ```rust
3324             'lifetime
3325             ```
3326             "#]],
3327         );
3328     }
3329
3330     #[test]
3331     fn hover_type_param() {
3332         check(
3333             r#"
3334 struct Foo<T>(T);
3335 trait Copy {}
3336 trait Clone {}
3337 trait Sized {}
3338 impl<T: Copy + Clone> Foo<T$0> where T: Sized {}
3339 "#,
3340             expect![[r#"
3341                 *T*
3342
3343                 ```rust
3344                 T: Copy + Clone + Sized
3345                 ```
3346             "#]],
3347         );
3348         check(
3349             r#"
3350 struct Foo<T>(T);
3351 impl<T> Foo<T$0> {}
3352 "#,
3353             expect![[r#"
3354                 *T*
3355
3356                 ```rust
3357                 T
3358                 ```
3359                 "#]],
3360         );
3361         // lifetimes aren't being substituted yet
3362         check(
3363             r#"
3364 struct Foo<T>(T);
3365 impl<T: 'static> Foo<T$0> {}
3366 "#,
3367             expect![[r#"
3368                 *T*
3369
3370                 ```rust
3371                 T: {error}
3372                 ```
3373                 "#]],
3374         );
3375     }
3376
3377     #[test]
3378     fn hover_const_param() {
3379         check(
3380             r#"
3381 struct Foo<const LEN: usize>;
3382 impl<const LEN: usize> Foo<LEN$0> {}
3383 "#,
3384             expect![[r#"
3385                 *LEN*
3386
3387                 ```rust
3388                 const LEN: usize
3389                 ```
3390             "#]],
3391         );
3392     }
3393 }