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