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