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