]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/hover.rs
Merge #9954
[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
967     #[test]
968     fn hover_shows_fn_signature_with_type_params() {
969         check(
970             r#"
971 pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { }
972
973 fn main() { let foo_test = fo$0o(); }
974         "#,
975             expect![[r#"
976                 *foo*
977
978                 ```rust
979                 test
980                 ```
981
982                 ```rust
983                 pub fn foo<'a, T>(b: &'a T) -> &'a str
984                 where
985                     T: AsRef<str>,
986                 ```
987             "#]],
988         );
989     }
990
991     #[test]
992     fn hover_shows_fn_signature_on_fn_name() {
993         check(
994             r#"
995 pub fn foo$0(a: u32, b: u32) -> u32 {}
996
997 fn main() { }
998 "#,
999             expect![[r#"
1000                 *foo*
1001
1002                 ```rust
1003                 test
1004                 ```
1005
1006                 ```rust
1007                 pub fn foo(a: u32, b: u32) -> u32
1008                 ```
1009             "#]],
1010         );
1011     }
1012
1013     #[test]
1014     fn hover_shows_fn_doc() {
1015         check(
1016             r#"
1017 /// # Example
1018 /// ```
1019 /// # use std::path::Path;
1020 /// #
1021 /// foo(Path::new("hello, world!"))
1022 /// ```
1023 pub fn foo$0(_: &Path) {}
1024
1025 fn main() { }
1026 "#,
1027             expect![[r##"
1028                 *foo*
1029
1030                 ```rust
1031                 test
1032                 ```
1033
1034                 ```rust
1035                 pub fn foo(_: &Path)
1036                 ```
1037
1038                 ---
1039
1040                 # Example
1041
1042                 ```
1043                 # use std::path::Path;
1044                 #
1045                 foo(Path::new("hello, world!"))
1046                 ```
1047             "##]],
1048         );
1049     }
1050
1051     #[test]
1052     fn hover_shows_fn_doc_attr_raw_string() {
1053         check(
1054             r##"
1055 #[doc = r#"Raw string doc attr"#]
1056 pub fn foo$0(_: &Path) {}
1057
1058 fn main() { }
1059 "##,
1060             expect![[r##"
1061                 *foo*
1062
1063                 ```rust
1064                 test
1065                 ```
1066
1067                 ```rust
1068                 pub fn foo(_: &Path)
1069                 ```
1070
1071                 ---
1072
1073                 Raw string doc attr
1074             "##]],
1075         );
1076     }
1077
1078     #[test]
1079     fn hover_shows_struct_field_info() {
1080         // Hovering over the field when instantiating
1081         check(
1082             r#"
1083 struct Foo { field_a: u32 }
1084
1085 fn main() {
1086     let foo = Foo { field_a$0: 0, };
1087 }
1088 "#,
1089             expect![[r#"
1090                 *field_a*
1091
1092                 ```rust
1093                 test::Foo
1094                 ```
1095
1096                 ```rust
1097                 field_a: u32
1098                 ```
1099             "#]],
1100         );
1101
1102         // Hovering over the field in the definition
1103         check(
1104             r#"
1105 struct Foo { field_a$0: u32 }
1106
1107 fn main() {
1108     let foo = Foo { field_a: 0 };
1109 }
1110 "#,
1111             expect![[r#"
1112                 *field_a*
1113
1114                 ```rust
1115                 test::Foo
1116                 ```
1117
1118                 ```rust
1119                 field_a: u32
1120                 ```
1121             "#]],
1122         );
1123     }
1124
1125     #[test]
1126     fn hover_const_static() {
1127         check(
1128             r#"const foo$0: u32 = 123;"#,
1129             expect![[r#"
1130                 *foo*
1131
1132                 ```rust
1133                 test
1134                 ```
1135
1136                 ```rust
1137                 const foo: u32
1138                 ```
1139             "#]],
1140         );
1141         check(
1142             r#"static foo$0: u32 = 456;"#,
1143             expect![[r#"
1144                 *foo*
1145
1146                 ```rust
1147                 test
1148                 ```
1149
1150                 ```rust
1151                 static foo: u32
1152                 ```
1153             "#]],
1154         );
1155     }
1156
1157     #[test]
1158     fn hover_default_generic_types() {
1159         check(
1160             r#"
1161 struct Test<K, T = u8> { k: K, t: T }
1162
1163 fn main() {
1164     let zz$0 = Test { t: 23u8, k: 33 };
1165 }"#,
1166             expect![[r#"
1167                 *zz*
1168
1169                 ```rust
1170                 let zz: Test<i32, u8>
1171                 ```
1172             "#]],
1173         );
1174     }
1175
1176     #[test]
1177     fn hover_some() {
1178         check(
1179             r#"
1180 enum Option<T> { Some(T) }
1181 use Option::Some;
1182
1183 fn main() { So$0me(12); }
1184 "#,
1185             expect![[r#"
1186                 *Some*
1187
1188                 ```rust
1189                 test::Option
1190                 ```
1191
1192                 ```rust
1193                 Some(T)
1194                 ```
1195             "#]],
1196         );
1197
1198         check(
1199             r#"
1200 enum Option<T> { Some(T) }
1201 use Option::Some;
1202
1203 fn main() { let b$0ar = Some(12); }
1204 "#,
1205             expect![[r#"
1206                 *bar*
1207
1208                 ```rust
1209                 let bar: Option<i32>
1210                 ```
1211             "#]],
1212         );
1213     }
1214
1215     #[test]
1216     fn hover_enum_variant() {
1217         check(
1218             r#"
1219 enum Option<T> {
1220     /// The None variant
1221     Non$0e
1222 }
1223 "#,
1224             expect![[r#"
1225                 *None*
1226
1227                 ```rust
1228                 test::Option
1229                 ```
1230
1231                 ```rust
1232                 None
1233                 ```
1234
1235                 ---
1236
1237                 The None variant
1238             "#]],
1239         );
1240
1241         check(
1242             r#"
1243 enum Option<T> {
1244     /// The Some variant
1245     Some(T)
1246 }
1247 fn main() {
1248     let s = Option::Som$0e(12);
1249 }
1250 "#,
1251             expect![[r#"
1252                 *Some*
1253
1254                 ```rust
1255                 test::Option
1256                 ```
1257
1258                 ```rust
1259                 Some(T)
1260                 ```
1261
1262                 ---
1263
1264                 The Some variant
1265             "#]],
1266         );
1267     }
1268
1269     #[test]
1270     fn hover_for_local_variable() {
1271         check(
1272             r#"fn func(foo: i32) { fo$0o; }"#,
1273             expect![[r#"
1274                 *foo*
1275
1276                 ```rust
1277                 foo: i32
1278                 ```
1279             "#]],
1280         )
1281     }
1282
1283     #[test]
1284     fn hover_for_local_variable_pat() {
1285         check(
1286             r#"fn func(fo$0o: i32) {}"#,
1287             expect![[r#"
1288                 *foo*
1289
1290                 ```rust
1291                 foo: i32
1292                 ```
1293             "#]],
1294         )
1295     }
1296
1297     #[test]
1298     fn hover_local_var_edge() {
1299         check(
1300             r#"fn func(foo: i32) { if true { $0foo; }; }"#,
1301             expect![[r#"
1302                 *foo*
1303
1304                 ```rust
1305                 foo: i32
1306                 ```
1307             "#]],
1308         )
1309     }
1310
1311     #[test]
1312     fn hover_for_param_edge() {
1313         check(
1314             r#"fn func($0foo: i32) {}"#,
1315             expect![[r#"
1316                 *foo*
1317
1318                 ```rust
1319                 foo: i32
1320                 ```
1321             "#]],
1322         )
1323     }
1324
1325     #[test]
1326     fn hover_for_param_with_multiple_traits() {
1327         check(
1328             r#"
1329             //- minicore: sized
1330             trait Deref {
1331                 type Target: ?Sized;
1332             }
1333             trait DerefMut {
1334                 type Target: ?Sized;
1335             }
1336             fn f(_x$0: impl Deref<Target=u8> + DerefMut<Target=u8>) {}"#,
1337             expect![[r#"
1338                 *_x*
1339
1340                 ```rust
1341                 _x: impl Deref<Target = u8> + DerefMut<Target = u8>
1342                 ```
1343             "#]],
1344         )
1345     }
1346
1347     #[test]
1348     fn test_hover_infer_associated_method_result() {
1349         check(
1350             r#"
1351 struct Thing { x: u32 }
1352
1353 impl Thing {
1354     fn new() -> Thing { Thing { x: 0 } }
1355 }
1356
1357 fn main() { let foo_$0test = Thing::new(); }
1358 "#,
1359             expect![[r#"
1360                 *foo_test*
1361
1362                 ```rust
1363                 let foo_test: Thing
1364                 ```
1365             "#]],
1366         )
1367     }
1368
1369     #[test]
1370     fn test_hover_infer_associated_method_exact() {
1371         check(
1372             r#"
1373 mod wrapper {
1374     struct Thing { x: u32 }
1375
1376     impl Thing {
1377         fn new() -> Thing { Thing { x: 0 } }
1378     }
1379 }
1380
1381 fn main() { let foo_test = wrapper::Thing::new$0(); }
1382 "#,
1383             expect![[r#"
1384                 *new*
1385
1386                 ```rust
1387                 test::wrapper::Thing
1388                 ```
1389
1390                 ```rust
1391                 fn new() -> Thing
1392                 ```
1393             "#]],
1394         )
1395     }
1396
1397     #[test]
1398     fn test_hover_infer_associated_const_in_pattern() {
1399         check(
1400             r#"
1401 struct X;
1402 impl X {
1403     const C: u32 = 1;
1404 }
1405
1406 fn main() {
1407     match 1 {
1408         X::C$0 => {},
1409         2 => {},
1410         _ => {}
1411     };
1412 }
1413 "#,
1414             expect![[r#"
1415                 *C*
1416
1417                 ```rust
1418                 test
1419                 ```
1420
1421                 ```rust
1422                 const C: u32
1423                 ```
1424             "#]],
1425         )
1426     }
1427
1428     #[test]
1429     fn test_hover_self() {
1430         check(
1431             r#"
1432 struct Thing { x: u32 }
1433 impl Thing {
1434     fn new() -> Self { Self$0 { x: 0 } }
1435 }
1436 "#,
1437             expect![[r#"
1438                 *Self*
1439
1440                 ```rust
1441                 test
1442                 ```
1443
1444                 ```rust
1445                 struct Thing
1446                 ```
1447             "#]],
1448         );
1449         check(
1450             r#"
1451 struct Thing { x: u32 }
1452 impl Thing {
1453     fn new() -> Self$0 { Self { 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 enum Thing { A }
1471 impl Thing {
1472     pub fn new() -> Self$0 { Thing::A }
1473 }
1474 "#,
1475             expect![[r#"
1476                 *Self*
1477
1478                 ```rust
1479                 test
1480                 ```
1481
1482                 ```rust
1483                 enum Thing
1484                 ```
1485             "#]],
1486         );
1487         check(
1488             r#"
1489         enum Thing { A }
1490         impl Thing {
1491             pub fn thing(a: Self$0) {}
1492         }
1493         "#,
1494             expect![[r#"
1495                 *Self*
1496
1497                 ```rust
1498                 test
1499                 ```
1500
1501                 ```rust
1502                 enum Thing
1503                 ```
1504             "#]],
1505         );
1506     }
1507
1508     #[test]
1509     fn test_hover_shadowing_pat() {
1510         check(
1511             r#"
1512 fn x() {}
1513
1514 fn y() {
1515     let x = 0i32;
1516     x$0;
1517 }
1518 "#,
1519             expect![[r#"
1520                 *x*
1521
1522                 ```rust
1523                 let x: i32
1524                 ```
1525             "#]],
1526         )
1527     }
1528
1529     #[test]
1530     fn test_hover_macro_invocation() {
1531         check(
1532             r#"
1533 macro_rules! foo { () => {} }
1534
1535 fn f() { fo$0o!(); }
1536 "#,
1537             expect![[r#"
1538                 *foo*
1539
1540                 ```rust
1541                 test
1542                 ```
1543
1544                 ```rust
1545                 macro_rules! foo
1546                 ```
1547             "#]],
1548         )
1549     }
1550
1551     #[test]
1552     fn test_hover_macro2_invocation() {
1553         check(
1554             r#"
1555 /// foo bar
1556 ///
1557 /// foo bar baz
1558 macro foo() {}
1559
1560 fn f() { fo$0o!(); }
1561 "#,
1562             expect![[r#"
1563                 *foo*
1564
1565                 ```rust
1566                 test
1567                 ```
1568
1569                 ```rust
1570                 macro foo
1571                 ```
1572
1573                 ---
1574
1575                 foo bar
1576
1577                 foo bar baz
1578             "#]],
1579         )
1580     }
1581
1582     #[test]
1583     fn test_hover_tuple_field() {
1584         check(
1585             r#"struct TS(String, i32$0);"#,
1586             expect![[r#"
1587                 *i32*
1588
1589                 ```rust
1590                 i32
1591                 ```
1592             "#]],
1593         )
1594     }
1595
1596     #[test]
1597     fn test_hover_through_macro() {
1598         check(
1599             r#"
1600 macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1601 fn foo() {}
1602 id! {
1603     fn bar() { fo$0o(); }
1604 }
1605 "#,
1606             expect![[r#"
1607                 *foo*
1608
1609                 ```rust
1610                 test
1611                 ```
1612
1613                 ```rust
1614                 fn foo()
1615                 ```
1616             "#]],
1617         );
1618     }
1619
1620     #[test]
1621     fn test_hover_through_expr_in_macro() {
1622         check(
1623             r#"
1624 macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1625 fn foo(bar:u32) { let a = id!(ba$0r); }
1626 "#,
1627             expect![[r#"
1628                 *bar*
1629
1630                 ```rust
1631                 bar: u32
1632                 ```
1633             "#]],
1634         );
1635     }
1636
1637     #[test]
1638     fn test_hover_through_expr_in_macro_recursive() {
1639         check(
1640             r#"
1641 macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
1642 macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
1643 fn foo(bar:u32) { let a = id!(ba$0r); }
1644 "#,
1645             expect![[r#"
1646                 *bar*
1647
1648                 ```rust
1649                 bar: u32
1650                 ```
1651             "#]],
1652         );
1653     }
1654
1655     #[test]
1656     fn test_hover_through_func_in_macro_recursive() {
1657         check(
1658             r#"
1659 macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
1660 macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
1661 fn bar() -> u32 { 0 }
1662 fn foo() { let a = id!([0u32, bar($0)] ); }
1663 "#,
1664             expect![[r#"
1665                 *bar()*
1666                 ```rust
1667                 u32
1668                 ```
1669             "#]],
1670         );
1671     }
1672
1673     #[test]
1674     fn test_hover_through_literal_string_in_macro() {
1675         check(
1676             r#"
1677 macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } }
1678 fn foo() {
1679     let mastered_for_itunes = "";
1680     let _ = arr!("Tr$0acks", &mastered_for_itunes);
1681 }
1682 "#,
1683             expect![[r#"
1684                 *"Tracks"*
1685                 ```rust
1686                 &str
1687                 ```
1688             "#]],
1689         );
1690     }
1691
1692     #[test]
1693     fn test_hover_through_assert_macro() {
1694         check(
1695             r#"
1696 #[rustc_builtin_macro]
1697 macro_rules! assert {}
1698
1699 fn bar() -> bool { true }
1700 fn foo() {
1701     assert!(ba$0r());
1702 }
1703 "#,
1704             expect![[r#"
1705                 *bar*
1706
1707                 ```rust
1708                 test
1709                 ```
1710
1711                 ```rust
1712                 fn bar() -> bool
1713                 ```
1714             "#]],
1715         );
1716     }
1717
1718     #[test]
1719     fn test_hover_through_literal_string_in_builtin_macro() {
1720         check_hover_no_result(
1721             r#"
1722             #[rustc_builtin_macro]
1723             macro_rules! format {}
1724
1725             fn foo() {
1726                 format!("hel$0lo {}", 0);
1727             }
1728 "#,
1729         );
1730     }
1731
1732     #[test]
1733     fn test_hover_non_ascii_space_doc() {
1734         check(
1735             "
1736 /// <- `\u{3000}` here
1737 fn foo() { }
1738
1739 fn bar() { fo$0o(); }
1740 ",
1741             expect![[r#"
1742                 *foo*
1743
1744                 ```rust
1745                 test
1746                 ```
1747
1748                 ```rust
1749                 fn foo()
1750                 ```
1751
1752                 ---
1753
1754                 \<- ` ` here
1755             "#]],
1756         );
1757     }
1758
1759     #[test]
1760     fn test_hover_function_show_qualifiers() {
1761         check(
1762             r#"async fn foo$0() {}"#,
1763             expect![[r#"
1764                 *foo*
1765
1766                 ```rust
1767                 test
1768                 ```
1769
1770                 ```rust
1771                 async fn foo()
1772                 ```
1773             "#]],
1774         );
1775         check(
1776             r#"pub const unsafe fn foo$0() {}"#,
1777             expect![[r#"
1778                 *foo*
1779
1780                 ```rust
1781                 test
1782                 ```
1783
1784                 ```rust
1785                 pub const unsafe fn foo()
1786                 ```
1787             "#]],
1788         );
1789         // Top level `pub(crate)` will be displayed as no visibility.
1790         check(
1791             r#"mod m { pub(crate) async unsafe extern "C" fn foo$0() {} }"#,
1792             expect![[r#"
1793                 *foo*
1794
1795                 ```rust
1796                 test::m
1797                 ```
1798
1799                 ```rust
1800                 pub(crate) async unsafe extern "C" fn foo()
1801                 ```
1802             "#]],
1803         );
1804     }
1805
1806     #[test]
1807     fn test_hover_trait_show_qualifiers() {
1808         check_actions(
1809             r"unsafe trait foo$0() {}",
1810             expect![[r#"
1811                 [
1812                     Implementation(
1813                         FilePosition {
1814                             file_id: FileId(
1815                                 0,
1816                             ),
1817                             offset: 13,
1818                         },
1819                     ),
1820                 ]
1821             "#]],
1822         );
1823     }
1824
1825     #[test]
1826     fn test_hover_extern_crate() {
1827         check(
1828             r#"
1829 //- /main.rs crate:main deps:std
1830 extern crate st$0d;
1831 //- /std/lib.rs crate:std
1832 //! Standard library for this test
1833 //!
1834 //! Printed?
1835 //! abc123
1836 "#,
1837             expect![[r#"
1838                 *std*
1839
1840                 ```rust
1841                 extern crate std
1842                 ```
1843
1844                 ---
1845
1846                 Standard library for this test
1847
1848                 Printed?
1849                 abc123
1850             "#]],
1851         );
1852         check(
1853             r#"
1854 //- /main.rs crate:main deps:std
1855 extern crate std as ab$0c;
1856 //- /std/lib.rs crate:std
1857 //! Standard library for this test
1858 //!
1859 //! Printed?
1860 //! abc123
1861 "#,
1862             expect![[r#"
1863                 *abc*
1864
1865                 ```rust
1866                 extern crate std
1867                 ```
1868
1869                 ---
1870
1871                 Standard library for this test
1872
1873                 Printed?
1874                 abc123
1875             "#]],
1876         );
1877     }
1878
1879     #[test]
1880     fn test_hover_mod_with_same_name_as_function() {
1881         check(
1882             r#"
1883 use self::m$0y::Bar;
1884 mod my { pub struct Bar; }
1885
1886 fn my() {}
1887 "#,
1888             expect![[r#"
1889                 *my*
1890
1891                 ```rust
1892                 test
1893                 ```
1894
1895                 ```rust
1896                 mod my
1897                 ```
1898             "#]],
1899         );
1900     }
1901
1902     #[test]
1903     fn test_hover_struct_doc_comment() {
1904         check(
1905             r#"
1906 /// This is an example
1907 /// multiline doc
1908 ///
1909 /// # Example
1910 ///
1911 /// ```
1912 /// let five = 5;
1913 ///
1914 /// assert_eq!(6, my_crate::add_one(5));
1915 /// ```
1916 struct Bar;
1917
1918 fn foo() { let bar = Ba$0r; }
1919 "#,
1920             expect![[r##"
1921                 *Bar*
1922
1923                 ```rust
1924                 test
1925                 ```
1926
1927                 ```rust
1928                 struct Bar
1929                 ```
1930
1931                 ---
1932
1933                 This is an example
1934                 multiline doc
1935
1936                 # Example
1937
1938                 ```
1939                 let five = 5;
1940
1941                 assert_eq!(6, my_crate::add_one(5));
1942                 ```
1943             "##]],
1944         );
1945     }
1946
1947     #[test]
1948     fn test_hover_struct_doc_attr() {
1949         check(
1950             r#"
1951 #[doc = "bar docs"]
1952 struct Bar;
1953
1954 fn foo() { let bar = Ba$0r; }
1955 "#,
1956             expect![[r#"
1957                 *Bar*
1958
1959                 ```rust
1960                 test
1961                 ```
1962
1963                 ```rust
1964                 struct Bar
1965                 ```
1966
1967                 ---
1968
1969                 bar docs
1970             "#]],
1971         );
1972     }
1973
1974     #[test]
1975     fn test_hover_struct_doc_attr_multiple_and_mixed() {
1976         check(
1977             r#"
1978 /// bar docs 0
1979 #[doc = "bar docs 1"]
1980 #[doc = "bar docs 2"]
1981 struct Bar;
1982
1983 fn foo() { let bar = Ba$0r; }
1984 "#,
1985             expect![[r#"
1986                 *Bar*
1987
1988                 ```rust
1989                 test
1990                 ```
1991
1992                 ```rust
1993                 struct Bar
1994                 ```
1995
1996                 ---
1997
1998                 bar docs 0
1999                 bar docs 1
2000                 bar docs 2
2001             "#]],
2002         );
2003     }
2004
2005     #[test]
2006     fn test_hover_external_url() {
2007         check(
2008             r#"
2009 pub struct Foo;
2010 /// [external](https://www.google.com)
2011 pub struct B$0ar
2012 "#,
2013             expect![[r#"
2014                 *Bar*
2015
2016                 ```rust
2017                 test
2018                 ```
2019
2020                 ```rust
2021                 pub struct Bar
2022                 ```
2023
2024                 ---
2025
2026                 [external](https://www.google.com)
2027             "#]],
2028         );
2029     }
2030
2031     // Check that we don't rewrite links which we can't identify
2032     #[test]
2033     fn test_hover_unknown_target() {
2034         check(
2035             r#"
2036 pub struct Foo;
2037 /// [baz](Baz)
2038 pub struct B$0ar
2039 "#,
2040             expect![[r#"
2041                 *Bar*
2042
2043                 ```rust
2044                 test
2045                 ```
2046
2047                 ```rust
2048                 pub struct Bar
2049                 ```
2050
2051                 ---
2052
2053                 [baz](Baz)
2054             "#]],
2055         );
2056     }
2057
2058     #[test]
2059     fn test_hover_no_links() {
2060         check_hover_no_links(
2061             r#"
2062 /// Test cases:
2063 /// case 1.  bare URL: https://www.example.com/
2064 /// case 2.  inline URL with title: [example](https://www.example.com/)
2065 /// case 3.  code reference: [`Result`]
2066 /// case 4.  code reference but miss footnote: [`String`]
2067 /// case 5.  autolink: <http://www.example.com/>
2068 /// case 6.  email address: <test@example.com>
2069 /// case 7.  reference: [example][example]
2070 /// case 8.  collapsed link: [example][]
2071 /// case 9.  shortcut link: [example]
2072 /// case 10. inline without URL: [example]()
2073 /// case 11. reference: [foo][foo]
2074 /// case 12. reference: [foo][bar]
2075 /// case 13. collapsed link: [foo][]
2076 /// case 14. shortcut link: [foo]
2077 /// case 15. inline without URL: [foo]()
2078 /// case 16. just escaped text: \[foo]
2079 /// case 17. inline link: [Foo](foo::Foo)
2080 ///
2081 /// [`Result`]: ../../std/result/enum.Result.html
2082 /// [^example]: https://www.example.com/
2083 pub fn fo$0o() {}
2084 "#,
2085             expect![[r#"
2086                 *foo*
2087
2088                 ```rust
2089                 test
2090                 ```
2091
2092                 ```rust
2093                 pub fn foo()
2094                 ```
2095
2096                 ---
2097
2098                 Test cases:
2099                 case 1.  bare URL: https://www.example.com/
2100                 case 2.  inline URL with title: [example](https://www.example.com/)
2101                 case 3.  code reference: `Result`
2102                 case 4.  code reference but miss footnote: `String`
2103                 case 5.  autolink: http://www.example.com/
2104                 case 6.  email address: test@example.com
2105                 case 7.  reference: example
2106                 case 8.  collapsed link: example
2107                 case 9.  shortcut link: example
2108                 case 10. inline without URL: example
2109                 case 11. reference: foo
2110                 case 12. reference: foo
2111                 case 13. collapsed link: foo
2112                 case 14. shortcut link: foo
2113                 case 15. inline without URL: foo
2114                 case 16. just escaped text: \[foo\]
2115                 case 17. inline link: Foo
2116
2117                 [^example]: https://www.example.com/
2118             "#]],
2119         );
2120     }
2121
2122     #[test]
2123     fn test_hover_macro_generated_struct_fn_doc_comment() {
2124         cov_mark::check!(hover_macro_generated_struct_fn_doc_comment);
2125
2126         check(
2127             r#"
2128 macro_rules! bar {
2129     () => {
2130         struct Bar;
2131         impl Bar {
2132             /// Do the foo
2133             fn foo(&self) {}
2134         }
2135     }
2136 }
2137
2138 bar!();
2139
2140 fn foo() { let bar = Bar; bar.fo$0o(); }
2141 "#,
2142             expect![[r#"
2143                 *foo*
2144
2145                 ```rust
2146                 test::Bar
2147                 ```
2148
2149                 ```rust
2150                 fn foo(&self)
2151                 ```
2152
2153                 ---
2154
2155                 Do the foo
2156             "#]],
2157         );
2158     }
2159
2160     #[test]
2161     fn test_hover_macro_generated_struct_fn_doc_attr() {
2162         cov_mark::check!(hover_macro_generated_struct_fn_doc_attr);
2163
2164         check(
2165             r#"
2166 macro_rules! bar {
2167     () => {
2168         struct Bar;
2169         impl Bar {
2170             #[doc = "Do the foo"]
2171             fn foo(&self) {}
2172         }
2173     }
2174 }
2175
2176 bar!();
2177
2178 fn foo() { let bar = Bar; bar.fo$0o(); }
2179 "#,
2180             expect![[r#"
2181                 *foo*
2182
2183                 ```rust
2184                 test::Bar
2185                 ```
2186
2187                 ```rust
2188                 fn foo(&self)
2189                 ```
2190
2191                 ---
2192
2193                 Do the foo
2194             "#]],
2195         );
2196     }
2197
2198     #[test]
2199     fn test_hover_trait_has_impl_action() {
2200         check_actions(
2201             r#"trait foo$0() {}"#,
2202             expect![[r#"
2203                 [
2204                     Implementation(
2205                         FilePosition {
2206                             file_id: FileId(
2207                                 0,
2208                             ),
2209                             offset: 6,
2210                         },
2211                     ),
2212                 ]
2213             "#]],
2214         );
2215     }
2216
2217     #[test]
2218     fn test_hover_struct_has_impl_action() {
2219         check_actions(
2220             r"struct foo$0() {}",
2221             expect![[r#"
2222                 [
2223                     Implementation(
2224                         FilePosition {
2225                             file_id: FileId(
2226                                 0,
2227                             ),
2228                             offset: 7,
2229                         },
2230                     ),
2231                 ]
2232             "#]],
2233         );
2234     }
2235
2236     #[test]
2237     fn test_hover_union_has_impl_action() {
2238         check_actions(
2239             r#"union foo$0() {}"#,
2240             expect![[r#"
2241                 [
2242                     Implementation(
2243                         FilePosition {
2244                             file_id: FileId(
2245                                 0,
2246                             ),
2247                             offset: 6,
2248                         },
2249                     ),
2250                 ]
2251             "#]],
2252         );
2253     }
2254
2255     #[test]
2256     fn test_hover_enum_has_impl_action() {
2257         check_actions(
2258             r"enum foo$0() { A, B }",
2259             expect![[r#"
2260                 [
2261                     Implementation(
2262                         FilePosition {
2263                             file_id: FileId(
2264                                 0,
2265                             ),
2266                             offset: 5,
2267                         },
2268                     ),
2269                 ]
2270             "#]],
2271         );
2272     }
2273
2274     #[test]
2275     fn test_hover_self_has_impl_action() {
2276         check_actions(
2277             r#"struct foo where Self$0:;"#,
2278             expect![[r#"
2279                 [
2280                     Implementation(
2281                         FilePosition {
2282                             file_id: FileId(
2283                                 0,
2284                             ),
2285                             offset: 7,
2286                         },
2287                     ),
2288                 ]
2289             "#]],
2290         );
2291     }
2292
2293     #[test]
2294     fn test_hover_test_has_action() {
2295         check_actions(
2296             r#"
2297 #[test]
2298 fn foo_$0test() {}
2299 "#,
2300             expect![[r#"
2301                 [
2302                     Reference(
2303                         FilePosition {
2304                             file_id: FileId(
2305                                 0,
2306                             ),
2307                             offset: 11,
2308                         },
2309                     ),
2310                     Runnable(
2311                         Runnable {
2312                             use_name_in_title: false,
2313                             nav: NavigationTarget {
2314                                 file_id: FileId(
2315                                     0,
2316                                 ),
2317                                 full_range: 0..24,
2318                                 focus_range: 11..19,
2319                                 name: "foo_test",
2320                                 kind: Function,
2321                             },
2322                             kind: Test {
2323                                 test_id: Path(
2324                                     "foo_test",
2325                                 ),
2326                                 attr: TestAttr {
2327                                     ignore: false,
2328                                 },
2329                             },
2330                             cfg: None,
2331                         },
2332                     ),
2333                 ]
2334             "#]],
2335         );
2336     }
2337
2338     #[test]
2339     fn test_hover_test_mod_has_action() {
2340         check_actions(
2341             r#"
2342 mod tests$0 {
2343     #[test]
2344     fn foo_test() {}
2345 }
2346 "#,
2347             expect![[r#"
2348                 [
2349                     Runnable(
2350                         Runnable {
2351                             use_name_in_title: false,
2352                             nav: NavigationTarget {
2353                                 file_id: FileId(
2354                                     0,
2355                                 ),
2356                                 full_range: 0..46,
2357                                 focus_range: 4..9,
2358                                 name: "tests",
2359                                 kind: Module,
2360                                 description: "mod tests",
2361                             },
2362                             kind: TestMod {
2363                                 path: "tests",
2364                             },
2365                             cfg: None,
2366                         },
2367                     ),
2368                 ]
2369             "#]],
2370         );
2371     }
2372
2373     #[test]
2374     fn test_hover_struct_has_goto_type_action() {
2375         check_actions(
2376             r#"
2377 struct S{ f1: u32 }
2378
2379 fn main() { let s$0t = S{ f1:0 }; }
2380 "#,
2381             expect![[r#"
2382                 [
2383                     GoToType(
2384                         [
2385                             HoverGotoTypeData {
2386                                 mod_path: "test::S",
2387                                 nav: NavigationTarget {
2388                                     file_id: FileId(
2389                                         0,
2390                                     ),
2391                                     full_range: 0..19,
2392                                     focus_range: 7..8,
2393                                     name: "S",
2394                                     kind: Struct,
2395                                     description: "struct S",
2396                                 },
2397                             },
2398                         ],
2399                     ),
2400                 ]
2401             "#]],
2402         );
2403     }
2404
2405     #[test]
2406     fn test_hover_generic_struct_has_goto_type_actions() {
2407         check_actions(
2408             r#"
2409 struct Arg(u32);
2410 struct S<T>{ f1: T }
2411
2412 fn main() { let s$0t = S{ f1:Arg(0) }; }
2413 "#,
2414             expect![[r#"
2415                 [
2416                     GoToType(
2417                         [
2418                             HoverGotoTypeData {
2419                                 mod_path: "test::S",
2420                                 nav: NavigationTarget {
2421                                     file_id: FileId(
2422                                         0,
2423                                     ),
2424                                     full_range: 17..37,
2425                                     focus_range: 24..25,
2426                                     name: "S",
2427                                     kind: Struct,
2428                                     description: "struct S<T>",
2429                                 },
2430                             },
2431                             HoverGotoTypeData {
2432                                 mod_path: "test::Arg",
2433                                 nav: NavigationTarget {
2434                                     file_id: FileId(
2435                                         0,
2436                                     ),
2437                                     full_range: 0..16,
2438                                     focus_range: 7..10,
2439                                     name: "Arg",
2440                                     kind: Struct,
2441                                     description: "struct Arg",
2442                                 },
2443                             },
2444                         ],
2445                     ),
2446                 ]
2447             "#]],
2448         );
2449     }
2450
2451     #[test]
2452     fn test_hover_generic_struct_has_flattened_goto_type_actions() {
2453         check_actions(
2454             r#"
2455 struct Arg(u32);
2456 struct S<T>{ f1: T }
2457
2458 fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
2459 "#,
2460             expect![[r#"
2461                 [
2462                     GoToType(
2463                         [
2464                             HoverGotoTypeData {
2465                                 mod_path: "test::S",
2466                                 nav: NavigationTarget {
2467                                     file_id: FileId(
2468                                         0,
2469                                     ),
2470                                     full_range: 17..37,
2471                                     focus_range: 24..25,
2472                                     name: "S",
2473                                     kind: Struct,
2474                                     description: "struct S<T>",
2475                                 },
2476                             },
2477                             HoverGotoTypeData {
2478                                 mod_path: "test::Arg",
2479                                 nav: NavigationTarget {
2480                                     file_id: FileId(
2481                                         0,
2482                                     ),
2483                                     full_range: 0..16,
2484                                     focus_range: 7..10,
2485                                     name: "Arg",
2486                                     kind: Struct,
2487                                     description: "struct Arg",
2488                                 },
2489                             },
2490                         ],
2491                     ),
2492                 ]
2493             "#]],
2494         );
2495     }
2496
2497     #[test]
2498     fn test_hover_tuple_has_goto_type_actions() {
2499         check_actions(
2500             r#"
2501 struct A(u32);
2502 struct B(u32);
2503 mod M {
2504     pub struct C(u32);
2505 }
2506
2507 fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
2508 "#,
2509             expect![[r#"
2510                 [
2511                     GoToType(
2512                         [
2513                             HoverGotoTypeData {
2514                                 mod_path: "test::A",
2515                                 nav: NavigationTarget {
2516                                     file_id: FileId(
2517                                         0,
2518                                     ),
2519                                     full_range: 0..14,
2520                                     focus_range: 7..8,
2521                                     name: "A",
2522                                     kind: Struct,
2523                                     description: "struct A",
2524                                 },
2525                             },
2526                             HoverGotoTypeData {
2527                                 mod_path: "test::B",
2528                                 nav: NavigationTarget {
2529                                     file_id: FileId(
2530                                         0,
2531                                     ),
2532                                     full_range: 15..29,
2533                                     focus_range: 22..23,
2534                                     name: "B",
2535                                     kind: Struct,
2536                                     description: "struct B",
2537                                 },
2538                             },
2539                             HoverGotoTypeData {
2540                                 mod_path: "test::M::C",
2541                                 nav: NavigationTarget {
2542                                     file_id: FileId(
2543                                         0,
2544                                     ),
2545                                     full_range: 42..60,
2546                                     focus_range: 53..54,
2547                                     name: "C",
2548                                     kind: Struct,
2549                                     description: "pub struct C",
2550                                 },
2551                             },
2552                         ],
2553                     ),
2554                 ]
2555             "#]],
2556         );
2557     }
2558
2559     #[test]
2560     fn test_hover_return_impl_trait_has_goto_type_action() {
2561         check_actions(
2562             r#"
2563 trait Foo {}
2564 fn foo() -> impl Foo {}
2565
2566 fn main() { let s$0t = foo(); }
2567 "#,
2568             expect![[r#"
2569                 [
2570                     GoToType(
2571                         [
2572                             HoverGotoTypeData {
2573                                 mod_path: "test::Foo",
2574                                 nav: NavigationTarget {
2575                                     file_id: FileId(
2576                                         0,
2577                                     ),
2578                                     full_range: 0..12,
2579                                     focus_range: 6..9,
2580                                     name: "Foo",
2581                                     kind: Trait,
2582                                     description: "trait Foo",
2583                                 },
2584                             },
2585                         ],
2586                     ),
2587                 ]
2588             "#]],
2589         );
2590     }
2591
2592     #[test]
2593     fn test_hover_generic_return_impl_trait_has_goto_type_action() {
2594         check_actions(
2595             r#"
2596 trait Foo<T> {}
2597 struct S;
2598 fn foo() -> impl Foo<S> {}
2599
2600 fn main() { let s$0t = foo(); }
2601 "#,
2602             expect![[r#"
2603                 [
2604                     GoToType(
2605                         [
2606                             HoverGotoTypeData {
2607                                 mod_path: "test::Foo",
2608                                 nav: NavigationTarget {
2609                                     file_id: FileId(
2610                                         0,
2611                                     ),
2612                                     full_range: 0..15,
2613                                     focus_range: 6..9,
2614                                     name: "Foo",
2615                                     kind: Trait,
2616                                     description: "trait Foo<T>",
2617                                 },
2618                             },
2619                             HoverGotoTypeData {
2620                                 mod_path: "test::S",
2621                                 nav: NavigationTarget {
2622                                     file_id: FileId(
2623                                         0,
2624                                     ),
2625                                     full_range: 16..25,
2626                                     focus_range: 23..24,
2627                                     name: "S",
2628                                     kind: Struct,
2629                                     description: "struct S",
2630                                 },
2631                             },
2632                         ],
2633                     ),
2634                 ]
2635             "#]],
2636         );
2637     }
2638
2639     #[test]
2640     fn test_hover_return_impl_traits_has_goto_type_action() {
2641         check_actions(
2642             r#"
2643 trait Foo {}
2644 trait Bar {}
2645 fn foo() -> impl Foo + Bar {}
2646
2647 fn main() { let s$0t = foo(); }
2648 "#,
2649             expect![[r#"
2650                 [
2651                     GoToType(
2652                         [
2653                             HoverGotoTypeData {
2654                                 mod_path: "test::Foo",
2655                                 nav: NavigationTarget {
2656                                     file_id: FileId(
2657                                         0,
2658                                     ),
2659                                     full_range: 0..12,
2660                                     focus_range: 6..9,
2661                                     name: "Foo",
2662                                     kind: Trait,
2663                                     description: "trait Foo",
2664                                 },
2665                             },
2666                             HoverGotoTypeData {
2667                                 mod_path: "test::Bar",
2668                                 nav: NavigationTarget {
2669                                     file_id: FileId(
2670                                         0,
2671                                     ),
2672                                     full_range: 13..25,
2673                                     focus_range: 19..22,
2674                                     name: "Bar",
2675                                     kind: Trait,
2676                                     description: "trait Bar",
2677                                 },
2678                             },
2679                         ],
2680                     ),
2681                 ]
2682             "#]],
2683         );
2684     }
2685
2686     #[test]
2687     fn test_hover_generic_return_impl_traits_has_goto_type_action() {
2688         check_actions(
2689             r#"
2690 trait Foo<T> {}
2691 trait Bar<T> {}
2692 struct S1 {}
2693 struct S2 {}
2694
2695 fn foo() -> impl Foo<S1> + Bar<S2> {}
2696
2697 fn main() { let s$0t = foo(); }
2698 "#,
2699             expect![[r#"
2700                 [
2701                     GoToType(
2702                         [
2703                             HoverGotoTypeData {
2704                                 mod_path: "test::Foo",
2705                                 nav: NavigationTarget {
2706                                     file_id: FileId(
2707                                         0,
2708                                     ),
2709                                     full_range: 0..15,
2710                                     focus_range: 6..9,
2711                                     name: "Foo",
2712                                     kind: Trait,
2713                                     description: "trait Foo<T>",
2714                                 },
2715                             },
2716                             HoverGotoTypeData {
2717                                 mod_path: "test::Bar",
2718                                 nav: NavigationTarget {
2719                                     file_id: FileId(
2720                                         0,
2721                                     ),
2722                                     full_range: 16..31,
2723                                     focus_range: 22..25,
2724                                     name: "Bar",
2725                                     kind: Trait,
2726                                     description: "trait Bar<T>",
2727                                 },
2728                             },
2729                             HoverGotoTypeData {
2730                                 mod_path: "test::S1",
2731                                 nav: NavigationTarget {
2732                                     file_id: FileId(
2733                                         0,
2734                                     ),
2735                                     full_range: 32..44,
2736                                     focus_range: 39..41,
2737                                     name: "S1",
2738                                     kind: Struct,
2739                                     description: "struct S1",
2740                                 },
2741                             },
2742                             HoverGotoTypeData {
2743                                 mod_path: "test::S2",
2744                                 nav: NavigationTarget {
2745                                     file_id: FileId(
2746                                         0,
2747                                     ),
2748                                     full_range: 45..57,
2749                                     focus_range: 52..54,
2750                                     name: "S2",
2751                                     kind: Struct,
2752                                     description: "struct S2",
2753                                 },
2754                             },
2755                         ],
2756                     ),
2757                 ]
2758             "#]],
2759         );
2760     }
2761
2762     #[test]
2763     fn test_hover_arg_impl_trait_has_goto_type_action() {
2764         check_actions(
2765             r#"
2766 trait Foo {}
2767 fn foo(ar$0g: &impl Foo) {}
2768 "#,
2769             expect![[r#"
2770                 [
2771                     GoToType(
2772                         [
2773                             HoverGotoTypeData {
2774                                 mod_path: "test::Foo",
2775                                 nav: NavigationTarget {
2776                                     file_id: FileId(
2777                                         0,
2778                                     ),
2779                                     full_range: 0..12,
2780                                     focus_range: 6..9,
2781                                     name: "Foo",
2782                                     kind: Trait,
2783                                     description: "trait Foo",
2784                                 },
2785                             },
2786                         ],
2787                     ),
2788                 ]
2789             "#]],
2790         );
2791     }
2792
2793     #[test]
2794     fn test_hover_arg_impl_traits_has_goto_type_action() {
2795         check_actions(
2796             r#"
2797 trait Foo {}
2798 trait Bar<T> {}
2799 struct S{}
2800
2801 fn foo(ar$0g: &impl Foo + Bar<S>) {}
2802 "#,
2803             expect![[r#"
2804                 [
2805                     GoToType(
2806                         [
2807                             HoverGotoTypeData {
2808                                 mod_path: "test::Foo",
2809                                 nav: NavigationTarget {
2810                                     file_id: FileId(
2811                                         0,
2812                                     ),
2813                                     full_range: 0..12,
2814                                     focus_range: 6..9,
2815                                     name: "Foo",
2816                                     kind: Trait,
2817                                     description: "trait Foo",
2818                                 },
2819                             },
2820                             HoverGotoTypeData {
2821                                 mod_path: "test::Bar",
2822                                 nav: NavigationTarget {
2823                                     file_id: FileId(
2824                                         0,
2825                                     ),
2826                                     full_range: 13..28,
2827                                     focus_range: 19..22,
2828                                     name: "Bar",
2829                                     kind: Trait,
2830                                     description: "trait Bar<T>",
2831                                 },
2832                             },
2833                             HoverGotoTypeData {
2834                                 mod_path: "test::S",
2835                                 nav: NavigationTarget {
2836                                     file_id: FileId(
2837                                         0,
2838                                     ),
2839                                     full_range: 29..39,
2840                                     focus_range: 36..37,
2841                                     name: "S",
2842                                     kind: Struct,
2843                                     description: "struct S",
2844                                 },
2845                             },
2846                         ],
2847                     ),
2848                 ]
2849             "#]],
2850         );
2851     }
2852
2853     #[test]
2854     fn test_hover_async_block_impl_trait_has_goto_type_action() {
2855         check_actions(
2856             r#"
2857 //- minicore: future
2858 struct S;
2859 fn foo() {
2860     let fo$0o = async { S };
2861 }
2862 "#,
2863             expect![[r#"
2864                 [
2865                     GoToType(
2866                         [
2867                             HoverGotoTypeData {
2868                                 mod_path: "core::future::Future",
2869                                 nav: NavigationTarget {
2870                                     file_id: FileId(
2871                                         1,
2872                                     ),
2873                                     full_range: 254..436,
2874                                     focus_range: 293..299,
2875                                     name: "Future",
2876                                     kind: Trait,
2877                                     description: "pub trait Future",
2878                                 },
2879                             },
2880                             HoverGotoTypeData {
2881                                 mod_path: "test::S",
2882                                 nav: NavigationTarget {
2883                                     file_id: FileId(
2884                                         0,
2885                                     ),
2886                                     full_range: 0..9,
2887                                     focus_range: 7..8,
2888                                     name: "S",
2889                                     kind: Struct,
2890                                     description: "struct S",
2891                                 },
2892                             },
2893                         ],
2894                     ),
2895                 ]
2896             "#]],
2897         );
2898     }
2899
2900     #[test]
2901     fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
2902         check_actions(
2903             r#"
2904 trait Foo<T> {}
2905 struct S {}
2906 fn foo(ar$0g: &impl Foo<S>) {}
2907 "#,
2908             expect![[r#"
2909                 [
2910                     GoToType(
2911                         [
2912                             HoverGotoTypeData {
2913                                 mod_path: "test::Foo",
2914                                 nav: NavigationTarget {
2915                                     file_id: FileId(
2916                                         0,
2917                                     ),
2918                                     full_range: 0..15,
2919                                     focus_range: 6..9,
2920                                     name: "Foo",
2921                                     kind: Trait,
2922                                     description: "trait Foo<T>",
2923                                 },
2924                             },
2925                             HoverGotoTypeData {
2926                                 mod_path: "test::S",
2927                                 nav: NavigationTarget {
2928                                     file_id: FileId(
2929                                         0,
2930                                     ),
2931                                     full_range: 16..27,
2932                                     focus_range: 23..24,
2933                                     name: "S",
2934                                     kind: Struct,
2935                                     description: "struct S",
2936                                 },
2937                             },
2938                         ],
2939                     ),
2940                 ]
2941             "#]],
2942         );
2943     }
2944
2945     #[test]
2946     fn test_hover_dyn_return_has_goto_type_action() {
2947         check_actions(
2948             r#"
2949 trait Foo {}
2950 struct S;
2951 impl Foo for S {}
2952
2953 struct B<T>{}
2954 fn foo() -> B<dyn Foo> {}
2955
2956 fn main() { let s$0t = foo(); }
2957 "#,
2958             expect![[r#"
2959                 [
2960                     GoToType(
2961                         [
2962                             HoverGotoTypeData {
2963                                 mod_path: "test::B",
2964                                 nav: NavigationTarget {
2965                                     file_id: FileId(
2966                                         0,
2967                                     ),
2968                                     full_range: 42..55,
2969                                     focus_range: 49..50,
2970                                     name: "B",
2971                                     kind: Struct,
2972                                     description: "struct B<T>",
2973                                 },
2974                             },
2975                             HoverGotoTypeData {
2976                                 mod_path: "test::Foo",
2977                                 nav: NavigationTarget {
2978                                     file_id: FileId(
2979                                         0,
2980                                     ),
2981                                     full_range: 0..12,
2982                                     focus_range: 6..9,
2983                                     name: "Foo",
2984                                     kind: Trait,
2985                                     description: "trait Foo",
2986                                 },
2987                             },
2988                         ],
2989                     ),
2990                 ]
2991             "#]],
2992         );
2993     }
2994
2995     #[test]
2996     fn test_hover_dyn_arg_has_goto_type_action() {
2997         check_actions(
2998             r#"
2999 trait Foo {}
3000 fn foo(ar$0g: &dyn Foo) {}
3001 "#,
3002             expect![[r#"
3003                 [
3004                     GoToType(
3005                         [
3006                             HoverGotoTypeData {
3007                                 mod_path: "test::Foo",
3008                                 nav: NavigationTarget {
3009                                     file_id: FileId(
3010                                         0,
3011                                     ),
3012                                     full_range: 0..12,
3013                                     focus_range: 6..9,
3014                                     name: "Foo",
3015                                     kind: Trait,
3016                                     description: "trait Foo",
3017                                 },
3018                             },
3019                         ],
3020                     ),
3021                 ]
3022             "#]],
3023         );
3024     }
3025
3026     #[test]
3027     fn test_hover_generic_dyn_arg_has_goto_type_action() {
3028         check_actions(
3029             r#"
3030 trait Foo<T> {}
3031 struct S {}
3032 fn foo(ar$0g: &dyn Foo<S>) {}
3033 "#,
3034             expect![[r#"
3035                 [
3036                     GoToType(
3037                         [
3038                             HoverGotoTypeData {
3039                                 mod_path: "test::Foo",
3040                                 nav: NavigationTarget {
3041                                     file_id: FileId(
3042                                         0,
3043                                     ),
3044                                     full_range: 0..15,
3045                                     focus_range: 6..9,
3046                                     name: "Foo",
3047                                     kind: Trait,
3048                                     description: "trait Foo<T>",
3049                                 },
3050                             },
3051                             HoverGotoTypeData {
3052                                 mod_path: "test::S",
3053                                 nav: NavigationTarget {
3054                                     file_id: FileId(
3055                                         0,
3056                                     ),
3057                                     full_range: 16..27,
3058                                     focus_range: 23..24,
3059                                     name: "S",
3060                                     kind: Struct,
3061                                     description: "struct S",
3062                                 },
3063                             },
3064                         ],
3065                     ),
3066                 ]
3067             "#]],
3068         );
3069     }
3070
3071     #[test]
3072     fn test_hover_goto_type_action_links_order() {
3073         check_actions(
3074             r#"
3075 trait ImplTrait<T> {}
3076 trait DynTrait<T> {}
3077 struct B<T> {}
3078 struct S {}
3079
3080 fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3081 "#,
3082             expect![[r#"
3083                 [
3084                     GoToType(
3085                         [
3086                             HoverGotoTypeData {
3087                                 mod_path: "test::ImplTrait",
3088                                 nav: NavigationTarget {
3089                                     file_id: FileId(
3090                                         0,
3091                                     ),
3092                                     full_range: 0..21,
3093                                     focus_range: 6..15,
3094                                     name: "ImplTrait",
3095                                     kind: Trait,
3096                                     description: "trait ImplTrait<T>",
3097                                 },
3098                             },
3099                             HoverGotoTypeData {
3100                                 mod_path: "test::B",
3101                                 nav: NavigationTarget {
3102                                     file_id: FileId(
3103                                         0,
3104                                     ),
3105                                     full_range: 43..57,
3106                                     focus_range: 50..51,
3107                                     name: "B",
3108                                     kind: Struct,
3109                                     description: "struct B<T>",
3110                                 },
3111                             },
3112                             HoverGotoTypeData {
3113                                 mod_path: "test::DynTrait",
3114                                 nav: NavigationTarget {
3115                                     file_id: FileId(
3116                                         0,
3117                                     ),
3118                                     full_range: 22..42,
3119                                     focus_range: 28..36,
3120                                     name: "DynTrait",
3121                                     kind: Trait,
3122                                     description: "trait DynTrait<T>",
3123                                 },
3124                             },
3125                             HoverGotoTypeData {
3126                                 mod_path: "test::S",
3127                                 nav: NavigationTarget {
3128                                     file_id: FileId(
3129                                         0,
3130                                     ),
3131                                     full_range: 58..69,
3132                                     focus_range: 65..66,
3133                                     name: "S",
3134                                     kind: Struct,
3135                                     description: "struct S",
3136                                 },
3137                             },
3138                         ],
3139                     ),
3140                 ]
3141             "#]],
3142         );
3143     }
3144
3145     #[test]
3146     fn test_hover_associated_type_has_goto_type_action() {
3147         check_actions(
3148             r#"
3149 trait Foo {
3150     type Item;
3151     fn get(self) -> Self::Item {}
3152 }
3153
3154 struct Bar{}
3155 struct S{}
3156
3157 impl Foo for S { type Item = Bar; }
3158
3159 fn test() -> impl Foo { S {} }
3160
3161 fn main() { let s$0t = test().get(); }
3162 "#,
3163             expect![[r#"
3164                 [
3165                     GoToType(
3166                         [
3167                             HoverGotoTypeData {
3168                                 mod_path: "test::Foo",
3169                                 nav: NavigationTarget {
3170                                     file_id: FileId(
3171                                         0,
3172                                     ),
3173                                     full_range: 0..62,
3174                                     focus_range: 6..9,
3175                                     name: "Foo",
3176                                     kind: Trait,
3177                                     description: "trait Foo",
3178                                 },
3179                             },
3180                         ],
3181                     ),
3182                 ]
3183             "#]],
3184         );
3185     }
3186
3187     #[test]
3188     fn test_hover_const_param_has_goto_type_action() {
3189         check_actions(
3190             r#"
3191 struct Bar;
3192 struct Foo<const BAR: Bar>;
3193
3194 impl<const BAR: Bar> Foo<BAR$0> {}
3195 "#,
3196             expect![[r#"
3197                 [
3198                     GoToType(
3199                         [
3200                             HoverGotoTypeData {
3201                                 mod_path: "test::Bar",
3202                                 nav: NavigationTarget {
3203                                     file_id: FileId(
3204                                         0,
3205                                     ),
3206                                     full_range: 0..11,
3207                                     focus_range: 7..10,
3208                                     name: "Bar",
3209                                     kind: Struct,
3210                                     description: "struct Bar",
3211                                 },
3212                             },
3213                         ],
3214                     ),
3215                 ]
3216             "#]],
3217         );
3218     }
3219
3220     #[test]
3221     fn test_hover_type_param_has_goto_type_action() {
3222         check_actions(
3223             r#"
3224 trait Foo {}
3225
3226 fn foo<T: Foo>(t: T$0){}
3227 "#,
3228             expect![[r#"
3229                 [
3230                     GoToType(
3231                         [
3232                             HoverGotoTypeData {
3233                                 mod_path: "test::Foo",
3234                                 nav: NavigationTarget {
3235                                     file_id: FileId(
3236                                         0,
3237                                     ),
3238                                     full_range: 0..12,
3239                                     focus_range: 6..9,
3240                                     name: "Foo",
3241                                     kind: Trait,
3242                                     description: "trait Foo",
3243                                 },
3244                             },
3245                         ],
3246                     ),
3247                 ]
3248             "#]],
3249         );
3250     }
3251
3252     #[test]
3253     fn test_hover_self_has_go_to_type() {
3254         check_actions(
3255             r#"
3256 struct Foo;
3257 impl Foo {
3258     fn foo(&self$0) {}
3259 }
3260 "#,
3261             expect![[r#"
3262                 [
3263                     GoToType(
3264                         [
3265                             HoverGotoTypeData {
3266                                 mod_path: "test::Foo",
3267                                 nav: NavigationTarget {
3268                                     file_id: FileId(
3269                                         0,
3270                                     ),
3271                                     full_range: 0..11,
3272                                     focus_range: 7..10,
3273                                     name: "Foo",
3274                                     kind: Struct,
3275                                     description: "struct Foo",
3276                                 },
3277                             },
3278                         ],
3279                     ),
3280                 ]
3281             "#]],
3282         );
3283     }
3284
3285     #[test]
3286     fn hover_displays_normalized_crate_names() {
3287         check(
3288             r#"
3289 //- /lib.rs crate:name-with-dashes
3290 pub mod wrapper {
3291     pub struct Thing { x: u32 }
3292
3293     impl Thing {
3294         pub fn new() -> Thing { Thing { x: 0 } }
3295     }
3296 }
3297
3298 //- /main.rs crate:main deps:name-with-dashes
3299 fn main() { let foo_test = name_with_dashes::wrapper::Thing::new$0(); }
3300 "#,
3301             expect![[r#"
3302             *new*
3303
3304             ```rust
3305             name_with_dashes::wrapper::Thing
3306             ```
3307
3308             ```rust
3309             pub fn new() -> Thing
3310             ```
3311             "#]],
3312         )
3313     }
3314
3315     #[test]
3316     fn hover_field_pat_shorthand_ref_match_ergonomics() {
3317         check(
3318             r#"
3319 struct S {
3320     f: i32,
3321 }
3322
3323 fn main() {
3324     let s = S { f: 0 };
3325     let S { f$0 } = &s;
3326 }
3327 "#,
3328             expect![[r#"
3329                 *f*
3330
3331                 ```rust
3332                 f: &i32
3333                 ```
3334             "#]],
3335         );
3336     }
3337
3338     #[test]
3339     fn hover_self_param_shows_type() {
3340         check(
3341             r#"
3342 struct Foo {}
3343 impl Foo {
3344     fn bar(&sel$0f) {}
3345 }
3346 "#,
3347             expect![[r#"
3348                 *self*
3349
3350                 ```rust
3351                 self: &Foo
3352                 ```
3353             "#]],
3354         );
3355     }
3356
3357     #[test]
3358     fn hover_self_param_shows_type_for_arbitrary_self_type() {
3359         check(
3360             r#"
3361 struct Arc<T>(T);
3362 struct Foo {}
3363 impl Foo {
3364     fn bar(sel$0f: Arc<Foo>) {}
3365 }
3366 "#,
3367             expect![[r#"
3368                 *self*
3369
3370                 ```rust
3371                 self: Arc<Foo>
3372                 ```
3373             "#]],
3374         );
3375     }
3376
3377     #[test]
3378     fn hover_doc_outer_inner() {
3379         check(
3380             r#"
3381 /// Be quick;
3382 mod Foo$0 {
3383     //! time is mana
3384
3385     /// This comment belongs to the function
3386     fn foo() {}
3387 }
3388 "#,
3389             expect![[r#"
3390                 *Foo*
3391
3392                 ```rust
3393                 test
3394                 ```
3395
3396                 ```rust
3397                 mod Foo
3398                 ```
3399
3400                 ---
3401
3402                 Be quick;
3403                 time is mana
3404             "#]],
3405         );
3406     }
3407
3408     #[test]
3409     fn hover_doc_outer_inner_attribue() {
3410         check(
3411             r#"
3412 #[doc = "Be quick;"]
3413 mod Foo$0 {
3414     #![doc = "time is mana"]
3415
3416     #[doc = "This comment belongs to the function"]
3417     fn foo() {}
3418 }
3419 "#,
3420             expect![[r#"
3421                 *Foo*
3422
3423                 ```rust
3424                 test
3425                 ```
3426
3427                 ```rust
3428                 mod Foo
3429                 ```
3430
3431                 ---
3432
3433                 Be quick;
3434                 time is mana
3435             "#]],
3436         );
3437     }
3438
3439     #[test]
3440     fn hover_doc_block_style_indentend() {
3441         check(
3442             r#"
3443 /**
3444     foo
3445     ```rust
3446     let x = 3;
3447     ```
3448 */
3449 fn foo$0() {}
3450 "#,
3451             expect![[r#"
3452                 *foo*
3453
3454                 ```rust
3455                 test
3456                 ```
3457
3458                 ```rust
3459                 fn foo()
3460                 ```
3461
3462                 ---
3463
3464                 foo
3465
3466                 ```rust
3467                 let x = 3;
3468                 ```
3469             "#]],
3470         );
3471     }
3472
3473     #[test]
3474     fn hover_comments_dont_highlight_parent() {
3475         cov_mark::check!(no_highlight_on_comment_hover);
3476         check_hover_no_result(
3477             r#"
3478 fn no_hover() {
3479     // no$0hover
3480 }
3481 "#,
3482         );
3483     }
3484
3485     #[test]
3486     fn hover_label() {
3487         check(
3488             r#"
3489 fn foo() {
3490     'label$0: loop {}
3491 }
3492 "#,
3493             expect![[r#"
3494             *'label*
3495
3496             ```rust
3497             'label
3498             ```
3499             "#]],
3500         );
3501     }
3502
3503     #[test]
3504     fn hover_lifetime() {
3505         check(
3506             r#"fn foo<'lifetime>(_: &'lifetime$0 ()) {}"#,
3507             expect![[r#"
3508             *'lifetime*
3509
3510             ```rust
3511             'lifetime
3512             ```
3513             "#]],
3514         );
3515     }
3516
3517     #[test]
3518     fn hover_type_param() {
3519         check(
3520             r#"
3521 //- minicore: sized
3522 struct Foo<T>(T);
3523 trait Copy {}
3524 trait Clone {}
3525 impl<T: Copy + Clone> Foo<T$0> where T: Sized {}
3526 "#,
3527             expect![[r#"
3528                 *T*
3529
3530                 ```rust
3531                 T: Copy + Clone
3532                 ```
3533             "#]],
3534         );
3535         check(
3536             r#"
3537 struct Foo<T>(T);
3538 impl<T> Foo<T$0> {}
3539 "#,
3540             expect![[r#"
3541                 *T*
3542
3543                 ```rust
3544                 T
3545                 ```
3546                 "#]],
3547         );
3548         // lifetimes bounds arent being tracked yet
3549         check(
3550             r#"
3551 struct Foo<T>(T);
3552 impl<T: 'static> Foo<T$0> {}
3553 "#,
3554             expect![[r#"
3555                 *T*
3556
3557                 ```rust
3558                 T
3559                 ```
3560                 "#]],
3561         );
3562     }
3563
3564     #[test]
3565     fn hover_type_param_not_sized() {
3566         check(
3567             r#"
3568 //- minicore: sized
3569 struct Foo<T>(T);
3570 trait Copy {}
3571 trait Clone {}
3572 impl<T: Copy + Clone> Foo<T$0> where T: ?Sized {}
3573 "#,
3574             expect![[r#"
3575                 *T*
3576
3577                 ```rust
3578                 T: Copy + Clone + ?Sized
3579                 ```
3580             "#]],
3581         );
3582     }
3583
3584     #[test]
3585     fn hover_const_param() {
3586         check(
3587             r#"
3588 struct Foo<const LEN: usize>;
3589 impl<const LEN: usize> Foo<LEN$0> {}
3590 "#,
3591             expect![[r#"
3592                 *LEN*
3593
3594                 ```rust
3595                 const LEN: usize
3596                 ```
3597             "#]],
3598         );
3599     }
3600
3601     #[test]
3602     fn hover_const_pat() {
3603         check(
3604             r#"
3605 /// This is a doc
3606 const FOO: usize = 3;
3607 fn foo() {
3608     match 5 {
3609         FOO$0 => (),
3610         _ => ()
3611     }
3612 }
3613 "#,
3614             expect![[r#"
3615                 *FOO*
3616
3617                 ```rust
3618                 test
3619                 ```
3620
3621                 ```rust
3622                 const FOO: usize
3623                 ```
3624
3625                 ---
3626
3627                 This is a doc
3628             "#]],
3629         );
3630     }
3631
3632     #[test]
3633     fn hover_mod_def() {
3634         check(
3635             r#"
3636 //- /main.rs
3637 mod foo$0;
3638 //- /foo.rs
3639 //! For the horde!
3640 "#,
3641             expect![[r#"
3642                 *foo*
3643
3644                 ```rust
3645                 test
3646                 ```
3647
3648                 ```rust
3649                 mod foo
3650                 ```
3651
3652                 ---
3653
3654                 For the horde!
3655             "#]],
3656         );
3657     }
3658
3659     #[test]
3660     fn hover_self_in_use() {
3661         check(
3662             r#"
3663 //! This should not appear
3664 mod foo {
3665     /// But this should appear
3666     pub mod bar {}
3667 }
3668 use foo::bar::{self$0};
3669 "#,
3670             expect![[r#"
3671                 *self*
3672
3673                 ```rust
3674                 test::foo
3675                 ```
3676
3677                 ```rust
3678                 mod bar
3679                 ```
3680
3681                 ---
3682
3683                 But this should appear
3684             "#]],
3685         )
3686     }
3687
3688     #[test]
3689     fn hover_keyword() {
3690         check(
3691             r#"
3692 //- /main.rs crate:main deps:std
3693 fn f() { retur$0n; }
3694 //- /libstd.rs crate:std
3695 /// Docs for return_keyword
3696 mod return_keyword {}
3697 "#,
3698             expect![[r#"
3699                 *return*
3700
3701                 ```rust
3702                 return
3703                 ```
3704
3705                 ---
3706
3707                 Docs for return_keyword
3708             "#]],
3709         );
3710     }
3711
3712     #[test]
3713     fn hover_builtin() {
3714         check(
3715             r#"
3716 //- /main.rs crate:main deps:std
3717 cosnt _: &str$0 = ""; }
3718
3719 //- /libstd.rs crate:std
3720 /// Docs for prim_str
3721 mod prim_str {}
3722 "#,
3723             expect![[r#"
3724                 *str*
3725
3726                 ```rust
3727                 str
3728                 ```
3729
3730                 ---
3731
3732                 Docs for prim_str
3733             "#]],
3734         );
3735     }
3736
3737     #[test]
3738     fn hover_macro_expanded_function() {
3739         check(
3740             r#"
3741 struct S<'a, T>(&'a T);
3742 trait Clone {}
3743 macro_rules! foo {
3744     () => {
3745         fn bar<'t, T: Clone + 't>(s: &mut S<'t, T>, t: u32) -> *mut u32 where
3746             't: 't + 't,
3747             for<'a> T: Clone + 'a
3748         { 0 as _ }
3749     };
3750 }
3751
3752 foo!();
3753
3754 fn main() {
3755     bar$0;
3756 }
3757 "#,
3758             expect![[r#"
3759                 *bar*
3760
3761                 ```rust
3762                 test
3763                 ```
3764
3765                 ```rust
3766                 fn bar<'t, T>(s: &mut S<'t, T>, t: u32) -> *mut u32
3767                 where
3768                     T: Clone + 't,
3769                     't: 't + 't,
3770                     for<'a> T: Clone + 'a,
3771                 ```
3772             "#]],
3773         )
3774     }
3775
3776     #[test]
3777     fn hover_intra_doc_links() {
3778         check(
3779             r#"
3780
3781 pub mod theitem {
3782     /// This is the item. Cool!
3783     pub struct TheItem;
3784 }
3785
3786 /// Gives you a [`TheItem$0`].
3787 ///
3788 /// [`TheItem`]: theitem::TheItem
3789 pub fn gimme() -> theitem::TheItem {
3790     theitem::TheItem
3791 }
3792 "#,
3793             expect![[r#"
3794                 *[`TheItem`]*
3795
3796                 ```rust
3797                 test::theitem
3798                 ```
3799
3800                 ```rust
3801                 pub struct TheItem
3802                 ```
3803
3804                 ---
3805
3806                 This is the item. Cool!
3807             "#]],
3808         );
3809     }
3810
3811     #[test]
3812     fn hover_generic_assoc() {
3813         check(
3814             r#"
3815 fn foo<T: A>() where T::Assoc$0: {}
3816
3817 trait A {
3818     type Assoc;
3819 }"#,
3820             expect![[r#"
3821                 *Assoc*
3822
3823                 ```rust
3824                 test
3825                 ```
3826
3827                 ```rust
3828                 type Assoc
3829                 ```
3830             "#]],
3831         );
3832         check(
3833             r#"
3834 fn foo<T: A>() {
3835     let _: <T>::Assoc$0;
3836 }
3837
3838 trait A {
3839     type Assoc;
3840 }"#,
3841             expect![[r#"
3842                 *Assoc*
3843
3844                 ```rust
3845                 test
3846                 ```
3847
3848                 ```rust
3849                 type Assoc
3850                 ```
3851             "#]],
3852         );
3853         check(
3854             r#"
3855 trait A where
3856     Self::Assoc$0: ,
3857 {
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     }
3873
3874     #[test]
3875     fn string_shadowed_with_inner_items() {
3876         check(
3877             r#"
3878 //- /main.rs crate:main deps:alloc
3879
3880 /// Custom `String` type.
3881 struct String;
3882
3883 fn f() {
3884     let _: String$0;
3885
3886     fn inner() {}
3887 }
3888
3889 //- /alloc.rs crate:alloc
3890 #[prelude_import]
3891 pub use string::*;
3892
3893 mod string {
3894     /// This is `alloc::String`.
3895     pub struct String;
3896 }
3897 "#,
3898             expect![[r#"
3899                 *String*
3900
3901                 ```rust
3902                 main
3903                 ```
3904
3905                 ```rust
3906                 struct String
3907                 ```
3908
3909                 ---
3910
3911                 Custom `String` type.
3912             "#]],
3913         )
3914     }
3915
3916     #[test]
3917     fn function_doesnt_shadow_crate_in_use_tree() {
3918         check(
3919             r#"
3920 //- /main.rs crate:main deps:foo
3921 use foo$0::{foo};
3922
3923 //- /foo.rs crate:foo
3924 pub fn foo() {}
3925 "#,
3926             expect![[r#"
3927                 *foo*
3928
3929                 ```rust
3930                 extern crate foo
3931                 ```
3932             "#]],
3933         )
3934     }
3935
3936     #[test]
3937     fn hover_feature() {
3938         check(
3939             r#"#![feature(box_syntax$0)]"#,
3940             expect![[r##"
3941                 *box_syntax*
3942                 ```
3943                 box_syntax
3944                 ```
3945                 ___
3946
3947                 # `box_syntax`
3948
3949                 The tracking issue for this feature is: [#49733]
3950
3951                 [#49733]: https://github.com/rust-lang/rust/issues/49733
3952
3953                 See also [`box_patterns`](box-patterns.md)
3954
3955                 ------------------------
3956
3957                 Currently the only stable way to create a `Box` is via the `Box::new` method.
3958                 Also it is not possible in stable Rust to destructure a `Box` in a match
3959                 pattern. The unstable `box` keyword can be used to create a `Box`. An example
3960                 usage would be:
3961
3962                 ```rust
3963                 #![feature(box_syntax)]
3964
3965                 fn main() {
3966                     let b = box 5;
3967                 }
3968                 ```
3969
3970             "##]],
3971         )
3972     }
3973
3974     #[test]
3975     fn hover_lint() {
3976         check(
3977             r#"#![allow(arithmetic_overflow$0)]"#,
3978             expect![[r#"
3979                 *arithmetic_overflow*
3980                 ```
3981                 arithmetic_overflow
3982                 ```
3983                 ___
3984
3985                 arithmetic operation overflows
3986             "#]],
3987         )
3988     }
3989
3990     #[test]
3991     fn hover_clippy_lint() {
3992         check(
3993             r#"#![allow(clippy::almost_swapped$0)]"#,
3994             expect![[r#"
3995                 *almost_swapped*
3996                 ```
3997                 clippy::almost_swapped
3998                 ```
3999                 ___
4000
4001                 Checks for `foo = bar; bar = foo` sequences.
4002             "#]],
4003         )
4004     }
4005
4006     #[test]
4007     fn hover_attr_path_qualifier() {
4008         cov_mark::check!(name_ref_classify_attr_path_qualifier);
4009         check(
4010             r#"
4011 //- /foo.rs crate:foo
4012
4013 //- /lib.rs crate:main.rs deps:foo
4014 #[fo$0o::bar()]
4015 struct Foo;
4016 "#,
4017             expect![[r#"
4018                 *foo*
4019
4020                 ```rust
4021                 extern crate foo
4022                 ```
4023             "#]],
4024         )
4025     }
4026
4027     #[test]
4028     fn hover_rename() {
4029         check(
4030             r#"
4031 use self as foo$0;
4032 "#,
4033             expect![[r#"
4034                 *foo*
4035
4036                 ```rust
4037                 extern crate test
4038                 ```
4039             "#]],
4040         );
4041         check(
4042             r#"
4043 mod bar {}
4044 use bar::{self as foo$0};
4045 "#,
4046             expect![[r#"
4047                 *foo*
4048
4049                 ```rust
4050                 test
4051                 ```
4052
4053                 ```rust
4054                 mod bar
4055                 ```
4056             "#]],
4057         );
4058         check(
4059             r#"
4060 mod bar {
4061     use super as foo$0;
4062 }
4063 "#,
4064             expect![[r#"
4065                 *foo*
4066
4067                 ```rust
4068                 extern crate test
4069                 ```
4070             "#]],
4071         );
4072         check(
4073             r#"
4074 use crate as foo$0;
4075 "#,
4076             expect![[r#"
4077                 *foo*
4078
4079                 ```rust
4080                 extern crate test
4081                 ```
4082             "#]],
4083         );
4084     }
4085
4086     #[test]
4087     fn hover_derive_input() {
4088         check(
4089             r#"
4090 #[rustc_builtin_macro]
4091 pub macro Copy {}
4092 #[derive(Copy$0)]
4093 struct Foo;
4094 "#,
4095             expect![[r#"
4096                 *Copy*
4097
4098                 ```rust
4099                 test
4100                 ```
4101
4102                 ```rust
4103                 pub macro Copy
4104                 ```
4105             "#]],
4106         );
4107         check(
4108             r#"
4109 mod foo {
4110     #[rustc_builtin_macro]
4111     pub macro Copy {}
4112 }
4113 #[derive(foo::Copy$0)]
4114 struct Foo;
4115 "#,
4116             expect![[r#"
4117                 *Copy*
4118
4119                 ```rust
4120                 test
4121                 ```
4122
4123                 ```rust
4124                 pub macro Copy
4125                 ```
4126             "#]],
4127         );
4128     }
4129
4130     #[test]
4131     fn hover_range_math() {
4132         check_hover_range(
4133             r#"
4134 fn f() { let expr = $01 + 2 * 3$0 }
4135 "#,
4136             expect![[r#"
4137             ```rust
4138             i32
4139             ```"#]],
4140         );
4141
4142         check_hover_range(
4143             r#"
4144 fn f() { let expr = 1 $0+ 2 * $03 }
4145 "#,
4146             expect![[r#"
4147             ```rust
4148             i32
4149             ```"#]],
4150         );
4151
4152         check_hover_range(
4153             r#"
4154 fn f() { let expr = 1 + $02 * 3$0 }
4155 "#,
4156             expect![[r#"
4157             ```rust
4158             i32
4159             ```"#]],
4160         );
4161     }
4162
4163     #[test]
4164     fn hover_range_arrays() {
4165         check_hover_range(
4166             r#"
4167 fn f() { let expr = $0[1, 2, 3, 4]$0 }
4168 "#,
4169             expect![[r#"
4170             ```rust
4171             [i32; 4]
4172             ```"#]],
4173         );
4174
4175         check_hover_range(
4176             r#"
4177 fn f() { let expr = [1, 2, $03, 4]$0 }
4178 "#,
4179             expect![[r#"
4180             ```rust
4181             [i32; 4]
4182             ```"#]],
4183         );
4184
4185         check_hover_range(
4186             r#"
4187 fn f() { let expr = [1, 2, $03$0, 4] }
4188 "#,
4189             expect![[r#"
4190             ```rust
4191             i32
4192             ```"#]],
4193         );
4194     }
4195
4196     #[test]
4197     fn hover_range_functions() {
4198         check_hover_range(
4199             r#"
4200 fn f<T>(a: &[T]) { }
4201 fn b() { $0f$0(&[1, 2, 3, 4, 5]); }
4202 "#,
4203             expect![[r#"
4204             ```rust
4205             fn f<i32>(&[i32])
4206             ```"#]],
4207         );
4208
4209         check_hover_range(
4210             r#"
4211 fn f<T>(a: &[T]) { }
4212 fn b() { f($0&[1, 2, 3, 4, 5]$0); }
4213 "#,
4214             expect![[r#"
4215             ```rust
4216             &[i32; 5]
4217             ```"#]],
4218         );
4219     }
4220
4221     #[test]
4222     fn hover_range_shows_nothing_when_invalid() {
4223         check_hover_range_no_results(
4224             r#"
4225 fn f<T>(a: &[T]) { }
4226 fn b()$0 { f(&[1, 2, 3, 4, 5]); }$0
4227 "#,
4228         );
4229
4230         check_hover_range_no_results(
4231             r#"
4232 fn f<T>$0(a: &[T]) { }
4233 fn b() { f(&[1, 2, 3,$0 4, 5]); }
4234 "#,
4235         );
4236
4237         check_hover_range_no_results(
4238             r#"
4239 fn $0f() { let expr = [1, 2, 3, 4]$0 }
4240 "#,
4241         );
4242     }
4243
4244     #[test]
4245     fn hover_range_shows_unit_for_statements() {
4246         check_hover_range(
4247             r#"
4248 fn f<T>(a: &[T]) { }
4249 fn b() { $0f(&[1, 2, 3, 4, 5]); }$0
4250 "#,
4251             expect![[r#"
4252             ```rust
4253             ()
4254             ```"#]],
4255         );
4256
4257         check_hover_range(
4258             r#"
4259 fn f() { let expr$0 = $0[1, 2, 3, 4] }
4260 "#,
4261             expect![[r#"
4262             ```rust
4263             ()
4264             ```"#]],
4265         );
4266     }
4267
4268     #[test]
4269     fn hover_range_for_pat() {
4270         check_hover_range(
4271             r#"
4272 fn foo() {
4273     let $0x$0 = 0;
4274 }
4275 "#,
4276             expect![[r#"
4277                 ```rust
4278                 i32
4279                 ```"#]],
4280         );
4281
4282         check_hover_range(
4283             r#"
4284 fn foo() {
4285     let $0x$0 = "";
4286 }
4287 "#,
4288             expect![[r#"
4289                 ```rust
4290                 &str
4291                 ```"#]],
4292         );
4293     }
4294
4295     #[test]
4296     fn hover_range_shows_coercions_if_applicable_expr() {
4297         check_hover_range(
4298             r#"
4299 fn foo() {
4300     let x: &u32 = $0&&&&&0$0;
4301 }
4302 "#,
4303             expect![[r#"
4304                 ```text
4305                 Type:       &&&&&u32
4306                 Coerced to:     &u32
4307                 ```
4308             "#]],
4309         );
4310         check_hover_range(
4311             r#"
4312 fn foo() {
4313     let x: *const u32 = $0&0$0;
4314 }
4315 "#,
4316             expect![[r#"
4317                 ```text
4318                 Type:             &u32
4319                 Coerced to: *const u32
4320                 ```
4321             "#]],
4322         );
4323     }
4324
4325     #[test]
4326     fn hover_range_shows_type_actions() {
4327         check_actions(
4328             r#"
4329 struct Foo;
4330 fn foo() {
4331     let x: &Foo = $0&&&&&Foo$0;
4332 }
4333 "#,
4334             expect![[r#"
4335                 [
4336                     GoToType(
4337                         [
4338                             HoverGotoTypeData {
4339                                 mod_path: "test::Foo",
4340                                 nav: NavigationTarget {
4341                                     file_id: FileId(
4342                                         0,
4343                                     ),
4344                                     full_range: 0..11,
4345                                     focus_range: 7..10,
4346                                     name: "Foo",
4347                                     kind: Struct,
4348                                     description: "struct Foo",
4349                                 },
4350                             },
4351                         ],
4352                     ),
4353                 ]
4354             "#]],
4355         );
4356     }
4357
4358     #[test]
4359     fn hover_try_expr_res() {
4360         check_hover_range(
4361             r#"
4362 //- minicore:result
4363 struct FooError;
4364
4365 fn foo() -> Result<(), FooError> {
4366     Ok($0Result::<(), FooError>::Ok(())?$0)
4367 }
4368 "#,
4369             expect![[r#"
4370                 ```rust
4371                 ()
4372                 ```"#]],
4373         );
4374         check_hover_range(
4375             r#"
4376 //- minicore:result
4377 struct FooError;
4378 struct BarError;
4379
4380 fn foo() -> Result<(), FooError> {
4381     Ok($0Result::<(), BarError>::Ok(())?$0)
4382 }
4383 "#,
4384             expect![[r#"
4385                 ```text
4386                 Try Error Type: BarError
4387                 Propagated as:  FooError
4388                 ```
4389             "#]],
4390         );
4391     }
4392
4393     #[test]
4394     fn hover_try_expr() {
4395         check_hover_range(
4396             r#"
4397 struct NotResult<T, U>(T, U);
4398 struct Short;
4399 struct Looooong;
4400
4401 fn foo() -> NotResult<(), Looooong> {
4402     $0NotResult((), Short)?$0;
4403 }
4404 "#,
4405             expect![[r#"
4406                 ```text
4407                 Try Target Type:    NotResult<(), Short>
4408                 Propagated as:   NotResult<(), Looooong>
4409                 ```
4410             "#]],
4411         );
4412         check_hover_range(
4413             r#"
4414 struct NotResult<T, U>(T, U);
4415 struct Short;
4416 struct Looooong;
4417
4418 fn foo() -> NotResult<(), Short> {
4419     $0NotResult((), Looooong)?$0;
4420 }
4421 "#,
4422             expect![[r#"
4423                 ```text
4424                 Try Target Type: NotResult<(), Looooong>
4425                 Propagated as:      NotResult<(), Short>
4426                 ```
4427             "#]],
4428         );
4429     }
4430
4431     #[test]
4432     fn hover_try_expr_option() {
4433         cov_mark::check!(hover_try_expr_opt_opt);
4434         check_hover_range(
4435             r#"
4436 //- minicore: option, try
4437
4438 fn foo() -> Option<()> {
4439     $0Some(0)?$0;
4440     None
4441 }
4442 "#,
4443             expect![[r#"
4444                 ```rust
4445                 <Option<i32> as Try>::Output
4446                 ```"#]],
4447         );
4448     }
4449 }