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