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