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