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