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