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