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