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