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