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