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