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