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