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