]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/hover.rs
Merge #7366
[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
1830     #[test]
1831     fn test_hover_external_url() {
1832         check(
1833             r#"
1834 pub struct Foo;
1835 /// [external](https://www.google.com)
1836 pub struct B$0ar
1837 "#,
1838             expect![[r#"
1839                 *Bar*
1840
1841                 ```rust
1842                 test
1843                 ```
1844
1845                 ```rust
1846                 pub struct Bar
1847                 ```
1848
1849                 ---
1850
1851                 [external](https://www.google.com)
1852             "#]],
1853         );
1854     }
1855
1856     // Check that we don't rewrite links which we can't identify
1857     #[test]
1858     fn test_hover_unknown_target() {
1859         check(
1860             r#"
1861 pub struct Foo;
1862 /// [baz](Baz)
1863 pub struct B$0ar
1864 "#,
1865             expect![[r#"
1866                 *Bar*
1867
1868                 ```rust
1869                 test
1870                 ```
1871
1872                 ```rust
1873                 pub struct Bar
1874                 ```
1875
1876                 ---
1877
1878                 [baz](Baz)
1879             "#]],
1880         );
1881     }
1882
1883     #[test]
1884     fn test_doc_links_enum_variant() {
1885         check(
1886             r#"
1887 enum E {
1888     /// [E]
1889     V$0 { field: i32 }
1890 }
1891 "#,
1892             expect![[r#"
1893                 *V*
1894
1895                 ```rust
1896                 test::E
1897                 ```
1898
1899                 ```rust
1900                 V
1901                 ```
1902
1903                 ---
1904
1905                 [E](https://docs.rs/test/*/test/enum.E.html)
1906             "#]],
1907         );
1908     }
1909
1910     #[test]
1911     fn test_doc_links_field() {
1912         check(
1913             r#"
1914 struct S {
1915     /// [`S`]
1916     field$0: i32
1917 }
1918 "#,
1919             expect![[r#"
1920                 *field*
1921
1922                 ```rust
1923                 test::S
1924                 ```
1925
1926                 ```rust
1927                 field: i32
1928                 ```
1929
1930                 ---
1931
1932                 [`S`](https://docs.rs/test/*/test/struct.S.html)
1933             "#]],
1934         );
1935     }
1936
1937     #[test]
1938     fn test_hover_no_links() {
1939         check_hover_no_links(
1940             r#"
1941 /// Test cases:
1942 /// case 1.  bare URL: https://www.example.com/
1943 /// case 2.  inline URL with title: [example](https://www.example.com/)
1944 /// case 3.  code reference: [`Result`]
1945 /// case 4.  code reference but miss footnote: [`String`]
1946 /// case 5.  autolink: <http://www.example.com/>
1947 /// case 6.  email address: <test@example.com>
1948 /// case 7.  reference: [example][example]
1949 /// case 8.  collapsed link: [example][]
1950 /// case 9.  shortcut link: [example]
1951 /// case 10. inline without URL: [example]()
1952 /// case 11. reference: [foo][foo]
1953 /// case 12. reference: [foo][bar]
1954 /// case 13. collapsed link: [foo][]
1955 /// case 14. shortcut link: [foo]
1956 /// case 15. inline without URL: [foo]()
1957 /// case 16. just escaped text: \[foo]
1958 /// case 17. inline link: [Foo](foo::Foo)
1959 ///
1960 /// [`Result`]: ../../std/result/enum.Result.html
1961 /// [^example]: https://www.example.com/
1962 pub fn fo$0o() {}
1963 "#,
1964             expect![[r#"
1965                 *foo*
1966
1967                 ```rust
1968                 test
1969                 ```
1970
1971                 ```rust
1972                 pub fn foo()
1973                 ```
1974
1975                 ---
1976
1977                 Test cases:
1978                 case 1.  bare URL: https://www.example.com/
1979                 case 2.  inline URL with title: [example](https://www.example.com/)
1980                 case 3.  code reference: `Result`
1981                 case 4.  code reference but miss footnote: `String`
1982                 case 5.  autolink: http://www.example.com/
1983                 case 6.  email address: test@example.com
1984                 case 7.  reference: example
1985                 case 8.  collapsed link: example
1986                 case 9.  shortcut link: example
1987                 case 10. inline without URL: example
1988                 case 11. reference: foo
1989                 case 12. reference: foo
1990                 case 13. collapsed link: foo
1991                 case 14. shortcut link: foo
1992                 case 15. inline without URL: foo
1993                 case 16. just escaped text: \[foo]
1994                 case 17. inline link: Foo
1995
1996                 [^example]: https://www.example.com/
1997             "#]],
1998         );
1999     }
2000
2001     #[test]
2002     fn test_hover_macro_generated_struct_fn_doc_comment() {
2003         mark::check!(hover_macro_generated_struct_fn_doc_comment);
2004
2005         check(
2006             r#"
2007 macro_rules! bar {
2008     () => {
2009         struct Bar;
2010         impl Bar {
2011             /// Do the foo
2012             fn foo(&self) {}
2013         }
2014     }
2015 }
2016
2017 bar!();
2018
2019 fn foo() { let bar = Bar; bar.fo$0o(); }
2020 "#,
2021             expect![[r#"
2022                 *foo*
2023
2024                 ```rust
2025                 test::Bar
2026                 ```
2027
2028                 ```rust
2029                 fn foo(&self)
2030                 ```
2031
2032                 ---
2033
2034                 Do the foo
2035             "#]],
2036         );
2037     }
2038
2039     #[test]
2040     fn test_hover_macro_generated_struct_fn_doc_attr() {
2041         mark::check!(hover_macro_generated_struct_fn_doc_attr);
2042
2043         check(
2044             r#"
2045 macro_rules! bar {
2046     () => {
2047         struct Bar;
2048         impl Bar {
2049             #[doc = "Do the foo"]
2050             fn foo(&self) {}
2051         }
2052     }
2053 }
2054
2055 bar!();
2056
2057 fn foo() { let bar = Bar; bar.fo$0o(); }
2058 "#,
2059             expect![[r#"
2060                 *foo*
2061
2062                 ```rust
2063                 test::Bar
2064                 ```
2065
2066                 ```rust
2067                 fn foo(&self)
2068                 ```
2069
2070                 ---
2071
2072                 Do the foo
2073             "#]],
2074         );
2075     }
2076
2077     #[test]
2078     fn test_hover_trait_has_impl_action() {
2079         check_actions(
2080             r#"trait foo$0() {}"#,
2081             expect![[r#"
2082                 [
2083                     Implementation(
2084                         FilePosition {
2085                             file_id: FileId(
2086                                 0,
2087                             ),
2088                             offset: 6,
2089                         },
2090                     ),
2091                 ]
2092             "#]],
2093         );
2094     }
2095
2096     #[test]
2097     fn test_hover_struct_has_impl_action() {
2098         check_actions(
2099             r"struct foo$0() {}",
2100             expect![[r#"
2101                 [
2102                     Implementation(
2103                         FilePosition {
2104                             file_id: FileId(
2105                                 0,
2106                             ),
2107                             offset: 7,
2108                         },
2109                     ),
2110                 ]
2111             "#]],
2112         );
2113     }
2114
2115     #[test]
2116     fn test_hover_union_has_impl_action() {
2117         check_actions(
2118             r#"union foo$0() {}"#,
2119             expect![[r#"
2120                 [
2121                     Implementation(
2122                         FilePosition {
2123                             file_id: FileId(
2124                                 0,
2125                             ),
2126                             offset: 6,
2127                         },
2128                     ),
2129                 ]
2130             "#]],
2131         );
2132     }
2133
2134     #[test]
2135     fn test_hover_enum_has_impl_action() {
2136         check_actions(
2137             r"enum foo$0() { A, B }",
2138             expect![[r#"
2139                 [
2140                     Implementation(
2141                         FilePosition {
2142                             file_id: FileId(
2143                                 0,
2144                             ),
2145                             offset: 5,
2146                         },
2147                     ),
2148                 ]
2149             "#]],
2150         );
2151     }
2152
2153     #[test]
2154     fn test_hover_self_has_impl_action() {
2155         check_actions(
2156             r#"struct foo where Self$0:;"#,
2157             expect![[r#"
2158                 [
2159                     Implementation(
2160                         FilePosition {
2161                             file_id: FileId(
2162                                 0,
2163                             ),
2164                             offset: 7,
2165                         },
2166                     ),
2167                 ]
2168             "#]],
2169         );
2170     }
2171
2172     #[test]
2173     fn test_hover_test_has_action() {
2174         check_actions(
2175             r#"
2176 #[test]
2177 fn foo_$0test() {}
2178 "#,
2179             expect![[r#"
2180                 [
2181                     Runnable(
2182                         Runnable {
2183                             nav: NavigationTarget {
2184                                 file_id: FileId(
2185                                     0,
2186                                 ),
2187                                 full_range: 0..24,
2188                                 focus_range: 11..19,
2189                                 name: "foo_test",
2190                                 kind: Function,
2191                             },
2192                             kind: Test {
2193                                 test_id: Path(
2194                                     "foo_test",
2195                                 ),
2196                                 attr: TestAttr {
2197                                     ignore: false,
2198                                 },
2199                             },
2200                             cfg: None,
2201                         },
2202                     ),
2203                 ]
2204             "#]],
2205         );
2206     }
2207
2208     #[test]
2209     fn test_hover_test_mod_has_action() {
2210         check_actions(
2211             r#"
2212 mod tests$0 {
2213     #[test]
2214     fn foo_test() {}
2215 }
2216 "#,
2217             expect![[r#"
2218                 [
2219                     Runnable(
2220                         Runnable {
2221                             nav: NavigationTarget {
2222                                 file_id: FileId(
2223                                     0,
2224                                 ),
2225                                 full_range: 0..46,
2226                                 focus_range: 4..9,
2227                                 name: "tests",
2228                                 kind: Module,
2229                             },
2230                             kind: TestMod {
2231                                 path: "tests",
2232                             },
2233                             cfg: None,
2234                         },
2235                     ),
2236                 ]
2237             "#]],
2238         );
2239     }
2240
2241     #[test]
2242     fn test_hover_struct_has_goto_type_action() {
2243         check_actions(
2244             r#"
2245 struct S{ f1: u32 }
2246
2247 fn main() { let s$0t = S{ f1:0 }; }
2248             "#,
2249             expect![[r#"
2250                 [
2251                     GoToType(
2252                         [
2253                             HoverGotoTypeData {
2254                                 mod_path: "test::S",
2255                                 nav: NavigationTarget {
2256                                     file_id: FileId(
2257                                         0,
2258                                     ),
2259                                     full_range: 0..19,
2260                                     focus_range: 7..8,
2261                                     name: "S",
2262                                     kind: Struct,
2263                                     description: "struct S",
2264                                 },
2265                             },
2266                         ],
2267                     ),
2268                 ]
2269             "#]],
2270         );
2271     }
2272
2273     #[test]
2274     fn test_hover_generic_struct_has_goto_type_actions() {
2275         check_actions(
2276             r#"
2277 struct Arg(u32);
2278 struct S<T>{ f1: T }
2279
2280 fn main() { let s$0t = S{ f1:Arg(0) }; }
2281 "#,
2282             expect![[r#"
2283                 [
2284                     GoToType(
2285                         [
2286                             HoverGotoTypeData {
2287                                 mod_path: "test::S",
2288                                 nav: NavigationTarget {
2289                                     file_id: FileId(
2290                                         0,
2291                                     ),
2292                                     full_range: 17..37,
2293                                     focus_range: 24..25,
2294                                     name: "S",
2295                                     kind: Struct,
2296                                     description: "struct S",
2297                                 },
2298                             },
2299                             HoverGotoTypeData {
2300                                 mod_path: "test::Arg",
2301                                 nav: NavigationTarget {
2302                                     file_id: FileId(
2303                                         0,
2304                                     ),
2305                                     full_range: 0..16,
2306                                     focus_range: 7..10,
2307                                     name: "Arg",
2308                                     kind: Struct,
2309                                     description: "struct Arg",
2310                                 },
2311                             },
2312                         ],
2313                     ),
2314                 ]
2315             "#]],
2316         );
2317     }
2318
2319     #[test]
2320     fn test_hover_generic_struct_has_flattened_goto_type_actions() {
2321         check_actions(
2322             r#"
2323 struct Arg(u32);
2324 struct S<T>{ f1: T }
2325
2326 fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
2327             "#,
2328             expect![[r#"
2329                 [
2330                     GoToType(
2331                         [
2332                             HoverGotoTypeData {
2333                                 mod_path: "test::S",
2334                                 nav: NavigationTarget {
2335                                     file_id: FileId(
2336                                         0,
2337                                     ),
2338                                     full_range: 17..37,
2339                                     focus_range: 24..25,
2340                                     name: "S",
2341                                     kind: Struct,
2342                                     description: "struct S",
2343                                 },
2344                             },
2345                             HoverGotoTypeData {
2346                                 mod_path: "test::Arg",
2347                                 nav: NavigationTarget {
2348                                     file_id: FileId(
2349                                         0,
2350                                     ),
2351                                     full_range: 0..16,
2352                                     focus_range: 7..10,
2353                                     name: "Arg",
2354                                     kind: Struct,
2355                                     description: "struct Arg",
2356                                 },
2357                             },
2358                         ],
2359                     ),
2360                 ]
2361             "#]],
2362         );
2363     }
2364
2365     #[test]
2366     fn test_hover_tuple_has_goto_type_actions() {
2367         check_actions(
2368             r#"
2369 struct A(u32);
2370 struct B(u32);
2371 mod M {
2372     pub struct C(u32);
2373 }
2374
2375 fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
2376 "#,
2377             expect![[r#"
2378                 [
2379                     GoToType(
2380                         [
2381                             HoverGotoTypeData {
2382                                 mod_path: "test::A",
2383                                 nav: NavigationTarget {
2384                                     file_id: FileId(
2385                                         0,
2386                                     ),
2387                                     full_range: 0..14,
2388                                     focus_range: 7..8,
2389                                     name: "A",
2390                                     kind: Struct,
2391                                     description: "struct A",
2392                                 },
2393                             },
2394                             HoverGotoTypeData {
2395                                 mod_path: "test::B",
2396                                 nav: NavigationTarget {
2397                                     file_id: FileId(
2398                                         0,
2399                                     ),
2400                                     full_range: 15..29,
2401                                     focus_range: 22..23,
2402                                     name: "B",
2403                                     kind: Struct,
2404                                     description: "struct B",
2405                                 },
2406                             },
2407                             HoverGotoTypeData {
2408                                 mod_path: "test::M::C",
2409                                 nav: NavigationTarget {
2410                                     file_id: FileId(
2411                                         0,
2412                                     ),
2413                                     full_range: 42..60,
2414                                     focus_range: 53..54,
2415                                     name: "C",
2416                                     kind: Struct,
2417                                     description: "pub struct C",
2418                                 },
2419                             },
2420                         ],
2421                     ),
2422                 ]
2423             "#]],
2424         );
2425     }
2426
2427     #[test]
2428     fn test_hover_return_impl_trait_has_goto_type_action() {
2429         check_actions(
2430             r#"
2431 trait Foo {}
2432 fn foo() -> impl Foo {}
2433
2434 fn main() { let s$0t = foo(); }
2435 "#,
2436             expect![[r#"
2437                 [
2438                     GoToType(
2439                         [
2440                             HoverGotoTypeData {
2441                                 mod_path: "test::Foo",
2442                                 nav: NavigationTarget {
2443                                     file_id: FileId(
2444                                         0,
2445                                     ),
2446                                     full_range: 0..12,
2447                                     focus_range: 6..9,
2448                                     name: "Foo",
2449                                     kind: Trait,
2450                                     description: "trait Foo",
2451                                 },
2452                             },
2453                         ],
2454                     ),
2455                 ]
2456             "#]],
2457         );
2458     }
2459
2460     #[test]
2461     fn test_hover_generic_return_impl_trait_has_goto_type_action() {
2462         check_actions(
2463             r#"
2464 trait Foo<T> {}
2465 struct S;
2466 fn foo() -> impl Foo<S> {}
2467
2468 fn main() { let s$0t = foo(); }
2469 "#,
2470             expect![[r#"
2471                 [
2472                     GoToType(
2473                         [
2474                             HoverGotoTypeData {
2475                                 mod_path: "test::Foo",
2476                                 nav: NavigationTarget {
2477                                     file_id: FileId(
2478                                         0,
2479                                     ),
2480                                     full_range: 0..15,
2481                                     focus_range: 6..9,
2482                                     name: "Foo",
2483                                     kind: Trait,
2484                                     description: "trait Foo",
2485                                 },
2486                             },
2487                             HoverGotoTypeData {
2488                                 mod_path: "test::S",
2489                                 nav: NavigationTarget {
2490                                     file_id: FileId(
2491                                         0,
2492                                     ),
2493                                     full_range: 16..25,
2494                                     focus_range: 23..24,
2495                                     name: "S",
2496                                     kind: Struct,
2497                                     description: "struct S",
2498                                 },
2499                             },
2500                         ],
2501                     ),
2502                 ]
2503             "#]],
2504         );
2505     }
2506
2507     #[test]
2508     fn test_hover_return_impl_traits_has_goto_type_action() {
2509         check_actions(
2510             r#"
2511 trait Foo {}
2512 trait Bar {}
2513 fn foo() -> impl Foo + Bar {}
2514
2515 fn main() { let s$0t = foo(); }
2516             "#,
2517             expect![[r#"
2518                 [
2519                     GoToType(
2520                         [
2521                             HoverGotoTypeData {
2522                                 mod_path: "test::Foo",
2523                                 nav: NavigationTarget {
2524                                     file_id: FileId(
2525                                         0,
2526                                     ),
2527                                     full_range: 0..12,
2528                                     focus_range: 6..9,
2529                                     name: "Foo",
2530                                     kind: Trait,
2531                                     description: "trait Foo",
2532                                 },
2533                             },
2534                             HoverGotoTypeData {
2535                                 mod_path: "test::Bar",
2536                                 nav: NavigationTarget {
2537                                     file_id: FileId(
2538                                         0,
2539                                     ),
2540                                     full_range: 13..25,
2541                                     focus_range: 19..22,
2542                                     name: "Bar",
2543                                     kind: Trait,
2544                                     description: "trait Bar",
2545                                 },
2546                             },
2547                         ],
2548                     ),
2549                 ]
2550             "#]],
2551         );
2552     }
2553
2554     #[test]
2555     fn test_hover_generic_return_impl_traits_has_goto_type_action() {
2556         check_actions(
2557             r#"
2558 trait Foo<T> {}
2559 trait Bar<T> {}
2560 struct S1 {}
2561 struct S2 {}
2562
2563 fn foo() -> impl Foo<S1> + Bar<S2> {}
2564
2565 fn main() { let s$0t = foo(); }
2566 "#,
2567             expect![[r#"
2568                 [
2569                     GoToType(
2570                         [
2571                             HoverGotoTypeData {
2572                                 mod_path: "test::Foo",
2573                                 nav: NavigationTarget {
2574                                     file_id: FileId(
2575                                         0,
2576                                     ),
2577                                     full_range: 0..15,
2578                                     focus_range: 6..9,
2579                                     name: "Foo",
2580                                     kind: Trait,
2581                                     description: "trait Foo",
2582                                 },
2583                             },
2584                             HoverGotoTypeData {
2585                                 mod_path: "test::Bar",
2586                                 nav: NavigationTarget {
2587                                     file_id: FileId(
2588                                         0,
2589                                     ),
2590                                     full_range: 16..31,
2591                                     focus_range: 22..25,
2592                                     name: "Bar",
2593                                     kind: Trait,
2594                                     description: "trait Bar",
2595                                 },
2596                             },
2597                             HoverGotoTypeData {
2598                                 mod_path: "test::S1",
2599                                 nav: NavigationTarget {
2600                                     file_id: FileId(
2601                                         0,
2602                                     ),
2603                                     full_range: 32..44,
2604                                     focus_range: 39..41,
2605                                     name: "S1",
2606                                     kind: Struct,
2607                                     description: "struct S1",
2608                                 },
2609                             },
2610                             HoverGotoTypeData {
2611                                 mod_path: "test::S2",
2612                                 nav: NavigationTarget {
2613                                     file_id: FileId(
2614                                         0,
2615                                     ),
2616                                     full_range: 45..57,
2617                                     focus_range: 52..54,
2618                                     name: "S2",
2619                                     kind: Struct,
2620                                     description: "struct S2",
2621                                 },
2622                             },
2623                         ],
2624                     ),
2625                 ]
2626             "#]],
2627         );
2628     }
2629
2630     #[test]
2631     fn test_hover_arg_impl_trait_has_goto_type_action() {
2632         check_actions(
2633             r#"
2634 trait Foo {}
2635 fn foo(ar$0g: &impl Foo) {}
2636 "#,
2637             expect![[r#"
2638                 [
2639                     GoToType(
2640                         [
2641                             HoverGotoTypeData {
2642                                 mod_path: "test::Foo",
2643                                 nav: NavigationTarget {
2644                                     file_id: FileId(
2645                                         0,
2646                                     ),
2647                                     full_range: 0..12,
2648                                     focus_range: 6..9,
2649                                     name: "Foo",
2650                                     kind: Trait,
2651                                     description: "trait Foo",
2652                                 },
2653                             },
2654                         ],
2655                     ),
2656                 ]
2657             "#]],
2658         );
2659     }
2660
2661     #[test]
2662     fn test_hover_arg_impl_traits_has_goto_type_action() {
2663         check_actions(
2664             r#"
2665 trait Foo {}
2666 trait Bar<T> {}
2667 struct S{}
2668
2669 fn foo(ar$0g: &impl Foo + Bar<S>) {}
2670 "#,
2671             expect![[r#"
2672                 [
2673                     GoToType(
2674                         [
2675                             HoverGotoTypeData {
2676                                 mod_path: "test::Foo",
2677                                 nav: NavigationTarget {
2678                                     file_id: FileId(
2679                                         0,
2680                                     ),
2681                                     full_range: 0..12,
2682                                     focus_range: 6..9,
2683                                     name: "Foo",
2684                                     kind: Trait,
2685                                     description: "trait Foo",
2686                                 },
2687                             },
2688                             HoverGotoTypeData {
2689                                 mod_path: "test::Bar",
2690                                 nav: NavigationTarget {
2691                                     file_id: FileId(
2692                                         0,
2693                                     ),
2694                                     full_range: 13..28,
2695                                     focus_range: 19..22,
2696                                     name: "Bar",
2697                                     kind: Trait,
2698                                     description: "trait Bar",
2699                                 },
2700                             },
2701                             HoverGotoTypeData {
2702                                 mod_path: "test::S",
2703                                 nav: NavigationTarget {
2704                                     file_id: FileId(
2705                                         0,
2706                                     ),
2707                                     full_range: 29..39,
2708                                     focus_range: 36..37,
2709                                     name: "S",
2710                                     kind: Struct,
2711                                     description: "struct S",
2712                                 },
2713                             },
2714                         ],
2715                     ),
2716                 ]
2717             "#]],
2718         );
2719     }
2720
2721     #[test]
2722     fn test_hover_async_block_impl_trait_has_goto_type_action() {
2723         check_actions(
2724             r#"
2725 struct S;
2726 fn foo() {
2727     let fo$0o = async { S };
2728 }
2729
2730 #[prelude_import] use future::*;
2731 mod future {
2732     #[lang = "future_trait"]
2733     pub trait Future { type Output; }
2734 }
2735 "#,
2736             expect![[r#"
2737                 [
2738                     GoToType(
2739                         [
2740                             HoverGotoTypeData {
2741                                 mod_path: "test::future::Future",
2742                                 nav: NavigationTarget {
2743                                     file_id: FileId(
2744                                         0,
2745                                     ),
2746                                     full_range: 101..163,
2747                                     focus_range: 140..146,
2748                                     name: "Future",
2749                                     kind: Trait,
2750                                     description: "pub trait Future",
2751                                 },
2752                             },
2753                             HoverGotoTypeData {
2754                                 mod_path: "test::S",
2755                                 nav: NavigationTarget {
2756                                     file_id: FileId(
2757                                         0,
2758                                     ),
2759                                     full_range: 0..9,
2760                                     focus_range: 7..8,
2761                                     name: "S",
2762                                     kind: Struct,
2763                                     description: "struct S",
2764                                 },
2765                             },
2766                         ],
2767                     ),
2768                 ]
2769             "#]],
2770         );
2771     }
2772
2773     #[test]
2774     fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
2775         check_actions(
2776             r#"
2777 trait Foo<T> {}
2778 struct S {}
2779 fn foo(ar$0g: &impl Foo<S>) {}
2780 "#,
2781             expect![[r#"
2782                 [
2783                     GoToType(
2784                         [
2785                             HoverGotoTypeData {
2786                                 mod_path: "test::Foo",
2787                                 nav: NavigationTarget {
2788                                     file_id: FileId(
2789                                         0,
2790                                     ),
2791                                     full_range: 0..15,
2792                                     focus_range: 6..9,
2793                                     name: "Foo",
2794                                     kind: Trait,
2795                                     description: "trait Foo",
2796                                 },
2797                             },
2798                             HoverGotoTypeData {
2799                                 mod_path: "test::S",
2800                                 nav: NavigationTarget {
2801                                     file_id: FileId(
2802                                         0,
2803                                     ),
2804                                     full_range: 16..27,
2805                                     focus_range: 23..24,
2806                                     name: "S",
2807                                     kind: Struct,
2808                                     description: "struct S",
2809                                 },
2810                             },
2811                         ],
2812                     ),
2813                 ]
2814             "#]],
2815         );
2816     }
2817
2818     #[test]
2819     fn test_hover_dyn_return_has_goto_type_action() {
2820         check_actions(
2821             r#"
2822 trait Foo {}
2823 struct S;
2824 impl Foo for S {}
2825
2826 struct B<T>{}
2827 fn foo() -> B<dyn Foo> {}
2828
2829 fn main() { let s$0t = foo(); }
2830 "#,
2831             expect![[r#"
2832                 [
2833                     GoToType(
2834                         [
2835                             HoverGotoTypeData {
2836                                 mod_path: "test::B",
2837                                 nav: NavigationTarget {
2838                                     file_id: FileId(
2839                                         0,
2840                                     ),
2841                                     full_range: 42..55,
2842                                     focus_range: 49..50,
2843                                     name: "B",
2844                                     kind: Struct,
2845                                     description: "struct B",
2846                                 },
2847                             },
2848                             HoverGotoTypeData {
2849                                 mod_path: "test::Foo",
2850                                 nav: NavigationTarget {
2851                                     file_id: FileId(
2852                                         0,
2853                                     ),
2854                                     full_range: 0..12,
2855                                     focus_range: 6..9,
2856                                     name: "Foo",
2857                                     kind: Trait,
2858                                     description: "trait Foo",
2859                                 },
2860                             },
2861                         ],
2862                     ),
2863                 ]
2864             "#]],
2865         );
2866     }
2867
2868     #[test]
2869     fn test_hover_dyn_arg_has_goto_type_action() {
2870         check_actions(
2871             r#"
2872 trait Foo {}
2873 fn foo(ar$0g: &dyn Foo) {}
2874 "#,
2875             expect![[r#"
2876                 [
2877                     GoToType(
2878                         [
2879                             HoverGotoTypeData {
2880                                 mod_path: "test::Foo",
2881                                 nav: NavigationTarget {
2882                                     file_id: FileId(
2883                                         0,
2884                                     ),
2885                                     full_range: 0..12,
2886                                     focus_range: 6..9,
2887                                     name: "Foo",
2888                                     kind: Trait,
2889                                     description: "trait Foo",
2890                                 },
2891                             },
2892                         ],
2893                     ),
2894                 ]
2895             "#]],
2896         );
2897     }
2898
2899     #[test]
2900     fn test_hover_generic_dyn_arg_has_goto_type_action() {
2901         check_actions(
2902             r#"
2903 trait Foo<T> {}
2904 struct S {}
2905 fn foo(ar$0g: &dyn Foo<S>) {}
2906 "#,
2907             expect![[r#"
2908                 [
2909                     GoToType(
2910                         [
2911                             HoverGotoTypeData {
2912                                 mod_path: "test::Foo",
2913                                 nav: NavigationTarget {
2914                                     file_id: FileId(
2915                                         0,
2916                                     ),
2917                                     full_range: 0..15,
2918                                     focus_range: 6..9,
2919                                     name: "Foo",
2920                                     kind: Trait,
2921                                     description: "trait Foo",
2922                                 },
2923                             },
2924                             HoverGotoTypeData {
2925                                 mod_path: "test::S",
2926                                 nav: NavigationTarget {
2927                                     file_id: FileId(
2928                                         0,
2929                                     ),
2930                                     full_range: 16..27,
2931                                     focus_range: 23..24,
2932                                     name: "S",
2933                                     kind: Struct,
2934                                     description: "struct S",
2935                                 },
2936                             },
2937                         ],
2938                     ),
2939                 ]
2940             "#]],
2941         );
2942     }
2943
2944     #[test]
2945     fn test_hover_goto_type_action_links_order() {
2946         check_actions(
2947             r#"
2948 trait ImplTrait<T> {}
2949 trait DynTrait<T> {}
2950 struct B<T> {}
2951 struct S {}
2952
2953 fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
2954             "#,
2955             expect![[r#"
2956                 [
2957                     GoToType(
2958                         [
2959                             HoverGotoTypeData {
2960                                 mod_path: "test::ImplTrait",
2961                                 nav: NavigationTarget {
2962                                     file_id: FileId(
2963                                         0,
2964                                     ),
2965                                     full_range: 0..21,
2966                                     focus_range: 6..15,
2967                                     name: "ImplTrait",
2968                                     kind: Trait,
2969                                     description: "trait ImplTrait",
2970                                 },
2971                             },
2972                             HoverGotoTypeData {
2973                                 mod_path: "test::B",
2974                                 nav: NavigationTarget {
2975                                     file_id: FileId(
2976                                         0,
2977                                     ),
2978                                     full_range: 43..57,
2979                                     focus_range: 50..51,
2980                                     name: "B",
2981                                     kind: Struct,
2982                                     description: "struct B",
2983                                 },
2984                             },
2985                             HoverGotoTypeData {
2986                                 mod_path: "test::DynTrait",
2987                                 nav: NavigationTarget {
2988                                     file_id: FileId(
2989                                         0,
2990                                     ),
2991                                     full_range: 22..42,
2992                                     focus_range: 28..36,
2993                                     name: "DynTrait",
2994                                     kind: Trait,
2995                                     description: "trait DynTrait",
2996                                 },
2997                             },
2998                             HoverGotoTypeData {
2999                                 mod_path: "test::S",
3000                                 nav: NavigationTarget {
3001                                     file_id: FileId(
3002                                         0,
3003                                     ),
3004                                     full_range: 58..69,
3005                                     focus_range: 65..66,
3006                                     name: "S",
3007                                     kind: Struct,
3008                                     description: "struct S",
3009                                 },
3010                             },
3011                         ],
3012                     ),
3013                 ]
3014             "#]],
3015         );
3016     }
3017
3018     #[test]
3019     fn test_hover_associated_type_has_goto_type_action() {
3020         check_actions(
3021             r#"
3022 trait Foo {
3023     type Item;
3024     fn get(self) -> Self::Item {}
3025 }
3026
3027 struct Bar{}
3028 struct S{}
3029
3030 impl Foo for S { type Item = Bar; }
3031
3032 fn test() -> impl Foo { S {} }
3033
3034 fn main() { let s$0t = test().get(); }
3035 "#,
3036             expect![[r#"
3037                 [
3038                     GoToType(
3039                         [
3040                             HoverGotoTypeData {
3041                                 mod_path: "test::Foo",
3042                                 nav: NavigationTarget {
3043                                     file_id: FileId(
3044                                         0,
3045                                     ),
3046                                     full_range: 0..62,
3047                                     focus_range: 6..9,
3048                                     name: "Foo",
3049                                     kind: Trait,
3050                                     description: "trait Foo",
3051                                 },
3052                             },
3053                         ],
3054                     ),
3055                 ]
3056             "#]],
3057         );
3058     }
3059
3060     #[test]
3061     fn test_hover_const_param_has_goto_type_action() {
3062         check_actions(
3063             r#"
3064 struct Bar;
3065 struct Foo<const BAR: Bar>;
3066
3067 impl<const BAR: Bar> Foo<BAR$0> {}
3068 "#,
3069             expect![[r#"
3070                 [
3071                     GoToType(
3072                         [
3073                             HoverGotoTypeData {
3074                                 mod_path: "test::Bar",
3075                                 nav: NavigationTarget {
3076                                     file_id: FileId(
3077                                         0,
3078                                     ),
3079                                     full_range: 0..11,
3080                                     focus_range: 7..10,
3081                                     name: "Bar",
3082                                     kind: Struct,
3083                                     description: "struct Bar",
3084                                 },
3085                             },
3086                         ],
3087                     ),
3088                 ]
3089             "#]],
3090         );
3091     }
3092
3093     #[test]
3094     fn test_hover_type_param_has_goto_type_action() {
3095         check_actions(
3096             r#"
3097 trait Foo {}
3098
3099 fn foo<T: Foo>(t: T$0){}
3100 "#,
3101             expect![[r#"
3102                 [
3103                     GoToType(
3104                         [
3105                             HoverGotoTypeData {
3106                                 mod_path: "test::Foo",
3107                                 nav: NavigationTarget {
3108                                     file_id: FileId(
3109                                         0,
3110                                     ),
3111                                     full_range: 0..12,
3112                                     focus_range: 6..9,
3113                                     name: "Foo",
3114                                     kind: Trait,
3115                                     description: "trait Foo",
3116                                 },
3117                             },
3118                         ],
3119                     ),
3120                 ]
3121             "#]],
3122         );
3123     }
3124
3125     #[test]
3126     fn test_hover_self_has_go_to_type() {
3127         check_actions(
3128             r#"
3129 struct Foo;
3130 impl Foo {
3131     fn foo(&self$0) {}
3132 }
3133 "#,
3134             expect![[r#"
3135                 [
3136                     GoToType(
3137                         [
3138                             HoverGotoTypeData {
3139                                 mod_path: "test::Foo",
3140                                 nav: NavigationTarget {
3141                                     file_id: FileId(
3142                                         0,
3143                                     ),
3144                                     full_range: 0..11,
3145                                     focus_range: 7..10,
3146                                     name: "Foo",
3147                                     kind: Struct,
3148                                     description: "struct Foo",
3149                                 },
3150                             },
3151                         ],
3152                     ),
3153                 ]
3154             "#]],
3155         );
3156     }
3157
3158     #[test]
3159     fn hover_displays_normalized_crate_names() {
3160         check(
3161             r#"
3162 //- /lib.rs crate:name-with-dashes
3163 pub mod wrapper {
3164     pub struct Thing { x: u32 }
3165
3166     impl Thing {
3167         pub fn new() -> Thing { Thing { x: 0 } }
3168     }
3169 }
3170
3171 //- /main.rs crate:main deps:name-with-dashes
3172 fn main() { let foo_test = name_with_dashes::wrapper::Thing::new$0(); }
3173 "#,
3174             expect![[r#"
3175             *new*
3176
3177             ```rust
3178             name_with_dashes::wrapper::Thing
3179             ```
3180
3181             ```rust
3182             pub fn new() -> Thing
3183             ```
3184             "#]],
3185         )
3186     }
3187
3188     #[test]
3189     fn hover_field_pat_shorthand_ref_match_ergonomics() {
3190         check(
3191             r#"
3192 struct S {
3193     f: i32,
3194 }
3195
3196 fn main() {
3197     let s = S { f: 0 };
3198     let S { f$0 } = &s;
3199 }
3200 "#,
3201             expect![[r#"
3202                 *f*
3203
3204                 ```rust
3205                 &i32
3206                 ```
3207             "#]],
3208         );
3209     }
3210
3211     #[test]
3212     fn hover_self_param_shows_type() {
3213         check(
3214             r#"
3215 struct Foo {}
3216 impl Foo {
3217     fn bar(&sel$0f) {}
3218 }
3219 "#,
3220             expect![[r#"
3221                 *self*
3222
3223                 ```rust
3224                 &Foo
3225                 ```
3226             "#]],
3227         );
3228     }
3229
3230     #[test]
3231     fn hover_self_param_shows_type_for_arbitrary_self_type() {
3232         check(
3233             r#"
3234 struct Arc<T>(T);
3235 struct Foo {}
3236 impl Foo {
3237     fn bar(sel$0f: Arc<Foo>) {}
3238 }
3239 "#,
3240             expect![[r#"
3241                 *self*
3242
3243                 ```rust
3244                 Arc<Foo>
3245                 ```
3246             "#]],
3247         );
3248     }
3249
3250     #[test]
3251     fn hover_doc_outer_inner() {
3252         check(
3253             r#"
3254 /// Be quick;
3255 mod Foo$0 {
3256     //! time is mana
3257
3258     /// This comment belongs to the function
3259     fn foo() {}
3260 }
3261 "#,
3262             expect![[r#"
3263                 *Foo*
3264
3265                 ```rust
3266                 test
3267                 ```
3268
3269                 ```rust
3270                 mod Foo
3271                 ```
3272
3273                 ---
3274
3275                 Be quick;
3276                 time is mana
3277             "#]],
3278         );
3279     }
3280
3281     #[test]
3282     fn hover_doc_outer_inner_attribue() {
3283         check(
3284             r#"
3285 #[doc = "Be quick;"]
3286 mod Foo$0 {
3287     #![doc = "time is mana"]
3288
3289     #[doc = "This comment belongs to the function"]
3290     fn foo() {}
3291 }
3292 "#,
3293             expect![[r#"
3294                 *Foo*
3295
3296                 ```rust
3297                 test
3298                 ```
3299
3300                 ```rust
3301                 mod Foo
3302                 ```
3303
3304                 ---
3305
3306                 Be quick;
3307                 time is mana
3308             "#]],
3309         );
3310     }
3311
3312     #[test]
3313     fn hover_comments_dont_highlight_parent() {
3314         check_hover_no_result(
3315             r#"
3316 fn no_hover() {
3317     // no$0hover
3318 }
3319 "#,
3320         );
3321     }
3322
3323     #[test]
3324     fn hover_label() {
3325         check(
3326             r#"
3327 fn foo() {
3328     'label$0: loop {}
3329 }
3330 "#,
3331             expect![[r#"
3332             *'label*
3333
3334             ```rust
3335             'label
3336             ```
3337             "#]],
3338         );
3339     }
3340
3341     #[test]
3342     fn hover_lifetime() {
3343         check(
3344             r#"fn foo<'lifetime>(_: &'lifetime$0 ()) {}"#,
3345             expect![[r#"
3346             *'lifetime*
3347
3348             ```rust
3349             'lifetime
3350             ```
3351             "#]],
3352         );
3353     }
3354
3355     #[test]
3356     fn hover_type_param() {
3357         check(
3358             r#"
3359 struct Foo<T>(T);
3360 trait Copy {}
3361 trait Clone {}
3362 trait Sized {}
3363 impl<T: Copy + Clone> Foo<T$0> where T: Sized {}
3364 "#,
3365             expect![[r#"
3366                 *T*
3367
3368                 ```rust
3369                 T: Copy + Clone + Sized
3370                 ```
3371             "#]],
3372         );
3373         check(
3374             r#"
3375 struct Foo<T>(T);
3376 impl<T> Foo<T$0> {}
3377 "#,
3378             expect![[r#"
3379                 *T*
3380
3381                 ```rust
3382                 T
3383                 ```
3384                 "#]],
3385         );
3386         // lifetimes aren't being substituted yet
3387         check(
3388             r#"
3389 struct Foo<T>(T);
3390 impl<T: 'static> Foo<T$0> {}
3391 "#,
3392             expect![[r#"
3393                 *T*
3394
3395                 ```rust
3396                 T: {error}
3397                 ```
3398                 "#]],
3399         );
3400     }
3401
3402     #[test]
3403     fn hover_const_param() {
3404         check(
3405             r#"
3406 struct Foo<const LEN: usize>;
3407 impl<const LEN: usize> Foo<LEN$0> {}
3408 "#,
3409             expect![[r#"
3410                 *LEN*
3411
3412                 ```rust
3413                 const LEN: usize
3414                 ```
3415             "#]],
3416         );
3417     }
3418 }