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