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