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