]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / ide / src / hover / tests.rs
CommitLineData
064997fb
FG
1use expect_test::{expect, Expect};
2use ide_db::base_db::{FileLoader, FileRange};
3use syntax::TextRange;
4
5use crate::{fixture, hover::HoverDocFormat, HoverConfig};
6
7fn check_hover_no_result(ra_fixture: &str) {
8 let (analysis, position) = fixture::position(ra_fixture);
9 let hover = analysis
10 .hover(
f2b60f7d
FG
11 &HoverConfig {
12 links_in_hover: true,
13 documentation: Some(HoverDocFormat::Markdown),
14 keywords: true,
15 },
064997fb
FG
16 FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
17 )
18 .unwrap();
19 assert!(hover.is_none(), "hover not expected but found: {:?}", hover.unwrap());
20}
21
22#[track_caller]
23fn check(ra_fixture: &str, expect: Expect) {
24 let (analysis, position) = fixture::position(ra_fixture);
25 let hover = analysis
26 .hover(
f2b60f7d
FG
27 &HoverConfig {
28 links_in_hover: true,
29 documentation: Some(HoverDocFormat::Markdown),
30 keywords: true,
31 },
064997fb
FG
32 FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
33 )
34 .unwrap()
35 .unwrap();
36
37 let content = analysis.db.file_text(position.file_id);
38 let hovered_element = &content[hover.range];
39
40 let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
41 expect.assert_eq(&actual)
42}
43
44fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
45 let (analysis, position) = fixture::position(ra_fixture);
46 let hover = analysis
47 .hover(
f2b60f7d
FG
48 &HoverConfig {
49 links_in_hover: false,
50 documentation: Some(HoverDocFormat::Markdown),
51 keywords: true,
52 },
064997fb
FG
53 FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
54 )
55 .unwrap()
56 .unwrap();
57
58 let content = analysis.db.file_text(position.file_id);
59 let hovered_element = &content[hover.range];
60
61 let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
62 expect.assert_eq(&actual)
63}
64
65fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) {
66 let (analysis, position) = fixture::position(ra_fixture);
67 let hover = analysis
68 .hover(
f2b60f7d
FG
69 &HoverConfig {
70 links_in_hover: true,
71 documentation: Some(HoverDocFormat::PlainText),
72 keywords: true,
73 },
064997fb
FG
74 FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
75 )
76 .unwrap()
77 .unwrap();
78
79 let content = analysis.db.file_text(position.file_id);
80 let hovered_element = &content[hover.range];
81
82 let actual = format!("*{}*\n{}\n", hovered_element, hover.info.markup);
83 expect.assert_eq(&actual)
84}
85
86fn check_actions(ra_fixture: &str, expect: Expect) {
87 let (analysis, file_id, position) = fixture::range_or_position(ra_fixture);
88 let hover = analysis
89 .hover(
f2b60f7d
FG
90 &HoverConfig {
91 links_in_hover: true,
92 documentation: Some(HoverDocFormat::Markdown),
93 keywords: true,
94 },
064997fb
FG
95 FileRange { file_id, range: position.range_or_empty() },
96 )
97 .unwrap()
98 .unwrap();
99 expect.assert_debug_eq(&hover.info.actions)
100}
101
102fn check_hover_range(ra_fixture: &str, expect: Expect) {
103 let (analysis, range) = fixture::range(ra_fixture);
104 let hover = analysis
105 .hover(
f2b60f7d
FG
106 &HoverConfig {
107 links_in_hover: false,
108 documentation: Some(HoverDocFormat::Markdown),
109 keywords: true,
110 },
064997fb
FG
111 range,
112 )
113 .unwrap()
114 .unwrap();
115 expect.assert_eq(hover.info.markup.as_str())
116}
117
118fn check_hover_range_no_results(ra_fixture: &str) {
119 let (analysis, range) = fixture::range(ra_fixture);
120 let hover = analysis
121 .hover(
f2b60f7d
FG
122 &HoverConfig {
123 links_in_hover: false,
124 documentation: Some(HoverDocFormat::Markdown),
125 keywords: true,
126 },
064997fb
FG
127 range,
128 )
129 .unwrap();
130 assert!(hover.is_none());
131}
132
133#[test]
134fn hover_descend_macros_avoids_duplicates() {
135 check(
136 r#"
137macro_rules! dupe_use {
138 ($local:ident) => {
139 {
140 $local;
141 $local;
142 }
143 }
144}
145fn foo() {
146 let local = 0;
147 dupe_use!(local$0);
148}
149"#,
150 expect![[r#"
151 *local*
152
153 ```rust
154 let local: i32
155 ```
156 "#]],
157 );
158}
159
160#[test]
161fn hover_shows_all_macro_descends() {
162 check(
163 r#"
164macro_rules! m {
165 ($name:ident) => {
166 /// Outer
167 fn $name() {}
168
169 mod module {
170 /// Inner
171 fn $name() {}
172 }
173 };
174}
175
176m!(ab$0c);
177 "#,
178 expect![[r#"
179 *abc*
180
181 ```rust
182 test::module
183 ```
184
185 ```rust
186 fn abc()
187 ```
188
189 ---
190
191 Inner
192 ---
193
194 ```rust
195 test
196 ```
197
198 ```rust
199 fn abc()
200 ```
201
202 ---
203
204 Outer
205 "#]],
206 );
207}
208
209#[test]
210fn hover_shows_type_of_an_expression() {
211 check(
212 r#"
213pub fn foo() -> u32 { 1 }
214
215fn main() {
216 let foo_test = foo()$0;
217}
218"#,
219 expect![[r#"
220 *foo()*
221 ```rust
222 u32
223 ```
224 "#]],
225 );
226}
227
228#[test]
229fn hover_remove_markdown_if_configured() {
230 check_hover_no_markdown(
231 r#"
232pub fn foo() -> u32 { 1 }
233
234fn main() {
235 let foo_test = foo()$0;
236}
237"#,
238 expect![[r#"
239 *foo()*
240 u32
241 "#]],
242 );
243}
244
245#[test]
246fn hover_shows_long_type_of_an_expression() {
247 check(
248 r#"
249struct Scan<A, B, C> { a: A, b: B, c: C }
250struct Iter<I> { inner: I }
251enum Option<T> { Some(T), None }
252
253struct OtherStruct<T> { i: T }
254
255fn scan<A, B, C>(a: A, b: B, c: C) -> Iter<Scan<OtherStruct<A>, B, C>> {
256 Iter { inner: Scan { a, b, c } }
257}
258
259fn main() {
260 let num: i32 = 55;
261 let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> Option<u32> {
262 Option::Some(*memo + value)
263 };
264 let number = 5u32;
265 let mut iter$0 = scan(OtherStruct { i: num }, closure, number);
266}
267"#,
268 expect![[r#"
269 *iter*
270
271 ```rust
272 let mut iter: Iter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> Option<u32>, u32>>
273 ```
274 "#]],
275 );
276}
277
278#[test]
279fn hover_shows_fn_signature() {
280 // Single file with result
281 check(
282 r#"
283pub fn foo() -> u32 { 1 }
284
285fn main() { let foo_test = fo$0o(); }
286"#,
287 expect![[r#"
288 *foo*
289
290 ```rust
291 test
292 ```
293
294 ```rust
295 pub fn foo() -> u32
296 ```
297 "#]],
298 );
299
300 // Multiple candidates but results are ambiguous.
301 check(
302 r#"
303//- /a.rs
304pub fn foo() -> u32 { 1 }
305
306//- /b.rs
307pub fn foo() -> &str { "" }
308
309//- /c.rs
310pub fn foo(a: u32, b: u32) {}
311
312//- /main.rs
313mod a;
314mod b;
315mod c;
316
317fn main() { let foo_test = fo$0o(); }
318 "#,
319 expect![[r#"
320 *foo*
321 ```rust
322 {unknown}
323 ```
324 "#]],
325 );
326
327 // Use literal `crate` in path
328 check(
329 r#"
330pub struct X;
331
332fn foo() -> crate::X { X }
333
334fn main() { f$0oo(); }
335 "#,
336 expect![[r#"
337 *foo*
338
339 ```rust
340 test
341 ```
342
343 ```rust
344 fn foo() -> crate::X
345 ```
346 "#]],
347 );
348
349 // Check `super` in path
350 check(
351 r#"
352pub struct X;
353
354mod m { pub fn foo() -> super::X { super::X } }
355
356fn main() { m::f$0oo(); }
357 "#,
358 expect![[r#"
359 *foo*
360
361 ```rust
362 test::m
363 ```
364
365 ```rust
366 pub fn foo() -> super::X
367 ```
368 "#]],
369 );
370}
371
372#[test]
373fn hover_omits_unnamed_where_preds() {
374 check(
375 r#"
376pub fn foo(bar: impl T) { }
377
378fn main() { fo$0o(); }
379 "#,
380 expect![[r#"
381 *foo*
382
383 ```rust
384 test
385 ```
386
387 ```rust
388 pub fn foo(bar: impl T)
389 ```
390 "#]],
391 );
392 check(
393 r#"
394pub fn foo<V: AsRef<str>>(bar: impl T, baz: V) { }
395
396fn main() { fo$0o(); }
397 "#,
398 expect![[r#"
399 *foo*
400
401 ```rust
402 test
403 ```
404
405 ```rust
406 pub fn foo<V>(bar: impl T, baz: V)
407 where
408 V: AsRef<str>,
409 ```
410 "#]],
411 );
412}
413
414#[test]
415fn hover_shows_fn_signature_with_type_params() {
416 check(
417 r#"
418pub fn foo<'a, T: AsRef<str>>(b: &'a T) -> &'a str { }
419
420fn main() { let foo_test = fo$0o(); }
421 "#,
422 expect![[r#"
423 *foo*
424
425 ```rust
426 test
427 ```
428
429 ```rust
430 pub fn foo<'a, T>(b: &'a T) -> &'a str
431 where
432 T: AsRef<str>,
433 ```
434 "#]],
435 );
436}
437
438#[test]
439fn hover_shows_fn_signature_on_fn_name() {
440 check(
441 r#"
442pub fn foo$0(a: u32, b: u32) -> u32 {}
443
444fn main() { }
445"#,
446 expect![[r#"
447 *foo*
448
449 ```rust
450 test
451 ```
452
453 ```rust
454 pub fn foo(a: u32, b: u32) -> u32
455 ```
456 "#]],
457 );
458}
459
460#[test]
461fn hover_shows_fn_doc() {
462 check(
463 r#"
464/// # Example
465/// ```
466/// # use std::path::Path;
467/// #
468/// foo(Path::new("hello, world!"))
469/// ```
470pub fn foo$0(_: &Path) {}
471
472fn main() { }
473"#,
474 expect![[r##"
475 *foo*
476
477 ```rust
478 test
479 ```
480
481 ```rust
482 pub fn foo(_: &Path)
483 ```
484
485 ---
486
487 # Example
488
489 ```
490 # use std::path::Path;
491 #
492 foo(Path::new("hello, world!"))
493 ```
494 "##]],
495 );
496}
497
498#[test]
499fn hover_shows_fn_doc_attr_raw_string() {
500 check(
501 r##"
502#[doc = r#"Raw string doc attr"#]
503pub fn foo$0(_: &Path) {}
504
505fn main() { }
506"##,
507 expect![[r##"
508 *foo*
509
510 ```rust
511 test
512 ```
513
514 ```rust
515 pub fn foo(_: &Path)
516 ```
517
518 ---
519
520 Raw string doc attr
521 "##]],
522 );
523}
524
525#[test]
526fn hover_shows_struct_field_info() {
527 // Hovering over the field when instantiating
528 check(
529 r#"
530struct Foo { field_a: u32 }
531
532fn main() {
533 let foo = Foo { field_a$0: 0, };
534}
535"#,
536 expect![[r#"
537 *field_a*
538
539 ```rust
540 test::Foo
541 ```
542
543 ```rust
544 field_a: u32
545 ```
546 "#]],
547 );
548
549 // Hovering over the field in the definition
550 check(
551 r#"
552struct Foo { field_a$0: u32 }
553
554fn main() {
555 let foo = Foo { field_a: 0 };
556}
557"#,
558 expect![[r#"
559 *field_a*
560
561 ```rust
562 test::Foo
563 ```
564
565 ```rust
566 field_a: u32
567 ```
568 "#]],
569 );
570}
571
572#[test]
573fn hover_const_static() {
574 check(
575 r#"const foo$0: u32 = 123;"#,
576 expect![[r#"
577 *foo*
578
579 ```rust
580 test
581 ```
582
583 ```rust
584 const foo: u32 = 123 (0x7B)
585 ```
586 "#]],
587 );
588 check(
589 r#"
590const foo$0: u32 = {
591 let x = foo();
592 x + 100
593};"#,
594 expect![[r#"
595 *foo*
596
597 ```rust
598 test
599 ```
600
601 ```rust
602 const foo: u32 = {
603 let x = foo();
604 x + 100
605 }
606 ```
607 "#]],
608 );
609
610 check(
611 r#"static foo$0: u32 = 456;"#,
612 expect![[r#"
613 *foo*
614
615 ```rust
616 test
617 ```
618
619 ```rust
620 static foo: u32 = 456
621 ```
622 "#]],
623 );
624}
625
626#[test]
627fn hover_default_generic_types() {
628 check(
629 r#"
630struct Test<K, T = u8> { k: K, t: T }
631
632fn main() {
633 let zz$0 = Test { t: 23u8, k: 33 };
634}"#,
635 expect![[r#"
636 *zz*
637
638 ```rust
639 let zz: Test<i32>
640 ```
641 "#]],
642 );
643 check_hover_range(
644 r#"
645struct Test<K, T = u8> { k: K, t: T }
646
647fn main() {
648 let $0zz$0 = Test { t: 23u8, k: 33 };
649}"#,
650 expect![[r#"
651 ```rust
652 Test<i32, u8>
653 ```"#]],
654 );
655}
656
657#[test]
658fn hover_some() {
659 check(
660 r#"
661enum Option<T> { Some(T) }
662use Option::Some;
663
664fn main() { So$0me(12); }
665"#,
666 expect![[r#"
667 *Some*
668
669 ```rust
670 test::Option
671 ```
672
673 ```rust
674 Some(T)
675 ```
676 "#]],
677 );
678
679 check(
680 r#"
681enum Option<T> { Some(T) }
682use Option::Some;
683
684fn main() { let b$0ar = Some(12); }
685"#,
686 expect![[r#"
687 *bar*
688
689 ```rust
690 let bar: Option<i32>
691 ```
692 "#]],
693 );
694}
695
696#[test]
697fn hover_enum_variant() {
698 check(
699 r#"
700enum Option<T> {
701 /// The None variant
702 Non$0e
703}
704"#,
705 expect![[r#"
706 *None*
707
708 ```rust
709 test::Option
710 ```
711
712 ```rust
713 None
714 ```
715
716 ---
717
718 The None variant
719 "#]],
720 );
721
722 check(
723 r#"
724enum Option<T> {
725 /// The Some variant
726 Some(T)
727}
728fn main() {
729 let s = Option::Som$0e(12);
730}
731"#,
732 expect![[r#"
733 *Some*
734
735 ```rust
736 test::Option
737 ```
738
739 ```rust
740 Some(T)
741 ```
742
743 ---
744
745 The Some variant
746 "#]],
747 );
748}
749
750#[test]
751fn hover_for_local_variable() {
752 check(
753 r#"fn func(foo: i32) { fo$0o; }"#,
754 expect![[r#"
755 *foo*
756
757 ```rust
758 foo: i32
759 ```
760 "#]],
761 )
762}
763
764#[test]
765fn hover_for_local_variable_pat() {
766 check(
767 r#"fn func(fo$0o: i32) {}"#,
768 expect![[r#"
769 *foo*
770
771 ```rust
772 foo: i32
773 ```
774 "#]],
775 )
776}
777
778#[test]
779fn hover_local_var_edge() {
780 check(
781 r#"fn func(foo: i32) { if true { $0foo; }; }"#,
782 expect![[r#"
783 *foo*
784
785 ```rust
786 foo: i32
787 ```
788 "#]],
789 )
790}
791
792#[test]
793fn hover_for_param_edge() {
794 check(
795 r#"fn func($0foo: i32) {}"#,
796 expect![[r#"
797 *foo*
798
799 ```rust
800 foo: i32
801 ```
802 "#]],
803 )
804}
805
806#[test]
807fn hover_for_param_with_multiple_traits() {
808 check(
809 r#"
810 //- minicore: sized
811 trait Deref {
812 type Target: ?Sized;
813 }
814 trait DerefMut {
815 type Target: ?Sized;
816 }
817 fn f(_x$0: impl Deref<Target=u8> + DerefMut<Target=u8>) {}"#,
818 expect![[r#"
819 *_x*
820
821 ```rust
822 _x: impl Deref<Target = u8> + DerefMut<Target = u8>
823 ```
824 "#]],
825 )
826}
827
828#[test]
829fn test_hover_infer_associated_method_result() {
830 check(
831 r#"
832struct Thing { x: u32 }
833
834impl Thing {
835 fn new() -> Thing { Thing { x: 0 } }
836}
837
838fn main() { let foo_$0test = Thing::new(); }
839"#,
840 expect![[r#"
841 *foo_test*
842
843 ```rust
844 let foo_test: Thing
845 ```
846 "#]],
847 )
848}
849
850#[test]
851fn test_hover_infer_associated_method_exact() {
852 check(
853 r#"
854mod wrapper {
855 pub struct Thing { x: u32 }
856
857 impl Thing {
858 pub fn new() -> Thing { Thing { x: 0 } }
859 }
860}
861
862fn main() { let foo_test = wrapper::Thing::new$0(); }
863"#,
864 expect![[r#"
865 *new*
866
867 ```rust
868 test::wrapper::Thing
869 ```
870
871 ```rust
872 pub fn new() -> Thing
873 ```
874 "#]],
875 )
876}
877
878#[test]
879fn test_hover_infer_associated_const_in_pattern() {
880 check(
881 r#"
882struct X;
883impl X {
884 const C: u32 = 1;
885}
886
887fn main() {
888 match 1 {
889 X::C$0 => {},
890 2 => {},
891 _ => {}
892 };
893}
894"#,
895 expect![[r#"
896 *C*
897
898 ```rust
899 test
900 ```
901
902 ```rust
903 const C: u32 = 1
904 ```
905 "#]],
906 )
907}
908
909#[test]
910fn test_hover_self() {
911 check(
912 r#"
913struct Thing { x: u32 }
914impl Thing {
915 fn new() -> Self { Self$0 { x: 0 } }
916}
917"#,
918 expect![[r#"
919 *Self*
920
921 ```rust
922 test
923 ```
924
925 ```rust
926 struct Thing
927 ```
928 "#]],
929 );
930 check(
931 r#"
932struct Thing { x: u32 }
933impl Thing {
934 fn new() -> Self$0 { Self { x: 0 } }
935}
936"#,
937 expect![[r#"
938 *Self*
939
940 ```rust
941 test
942 ```
943
944 ```rust
945 struct Thing
946 ```
947 "#]],
948 );
949 check(
950 r#"
951enum Thing { A }
952impl Thing {
953 pub fn new() -> Self$0 { Thing::A }
954}
955"#,
956 expect![[r#"
957 *Self*
958
959 ```rust
960 test
961 ```
962
963 ```rust
964 enum Thing
965 ```
966 "#]],
967 );
968 check(
969 r#"
970 enum Thing { A }
971 impl Thing {
972 pub fn thing(a: Self$0) {}
973 }
974 "#,
975 expect![[r#"
976 *Self*
977
978 ```rust
979 test
980 ```
981
982 ```rust
983 enum Thing
984 ```
985 "#]],
986 );
987}
988
989#[test]
990fn test_hover_shadowing_pat() {
991 check(
992 r#"
993fn x() {}
994
995fn y() {
996 let x = 0i32;
997 x$0;
998}
999"#,
1000 expect![[r#"
1001 *x*
1002
1003 ```rust
1004 let x: i32
1005 ```
1006 "#]],
1007 )
1008}
1009
1010#[test]
1011fn test_hover_macro_invocation() {
1012 check(
1013 r#"
1014macro_rules! foo { () => {} }
1015
1016fn f() { fo$0o!(); }
1017"#,
1018 expect![[r#"
1019 *foo*
1020
1021 ```rust
1022 test
1023 ```
1024
1025 ```rust
1026 macro_rules! foo
1027 ```
1028 "#]],
1029 )
1030}
1031
1032#[test]
1033fn test_hover_macro2_invocation() {
1034 check(
1035 r#"
1036/// foo bar
1037///
1038/// foo bar baz
1039macro foo() {}
1040
1041fn f() { fo$0o!(); }
1042"#,
1043 expect![[r#"
1044 *foo*
1045
1046 ```rust
1047 test
1048 ```
1049
1050 ```rust
1051 macro foo
1052 ```
1053
1054 ---
1055
1056 foo bar
1057
1058 foo bar baz
1059 "#]],
1060 )
1061}
1062
1063#[test]
1064fn test_hover_tuple_field() {
1065 check(
1066 r#"struct TS(String, i32$0);"#,
1067 expect![[r#"
1068 *i32*
1069
1070 ```rust
1071 i32
1072 ```
1073 "#]],
1074 )
1075}
1076
1077#[test]
1078fn test_hover_through_macro() {
1079 check(
1080 r#"
1081macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1082fn foo() {}
1083id! {
1084 fn bar() { fo$0o(); }
1085}
1086"#,
1087 expect![[r#"
1088 *foo*
1089
1090 ```rust
1091 test
1092 ```
1093
1094 ```rust
1095 fn foo()
1096 ```
1097 "#]],
1098 );
1099}
1100
1101#[test]
1102fn test_hover_through_attr() {
1103 check(
1104 r#"
1105//- proc_macros: identity
1106#[proc_macros::identity]
1107fn foo$0() {}
1108"#,
1109 expect![[r#"
1110 *foo*
1111
1112 ```rust
1113 test
1114 ```
1115
1116 ```rust
1117 fn foo()
1118 ```
1119 "#]],
1120 );
1121}
1122
1123#[test]
1124fn test_hover_through_expr_in_macro() {
1125 check(
1126 r#"
1127macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1128fn foo(bar:u32) { let a = id!(ba$0r); }
1129"#,
1130 expect![[r#"
1131 *bar*
1132
1133 ```rust
1134 bar: u32
1135 ```
1136 "#]],
1137 );
1138}
1139
1140#[test]
1141fn test_hover_through_expr_in_macro_recursive() {
1142 check(
1143 r#"
1144macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
1145macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
1146fn foo(bar:u32) { let a = id!(ba$0r); }
1147"#,
1148 expect![[r#"
1149 *bar*
1150
1151 ```rust
1152 bar: u32
1153 ```
1154 "#]],
1155 );
1156}
1157
1158#[test]
1159fn test_hover_through_func_in_macro_recursive() {
1160 check(
1161 r#"
1162macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
1163macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
1164fn bar() -> u32 { 0 }
1165fn foo() { let a = id!([0u32, bar($0)] ); }
1166"#,
1167 expect![[r#"
1168 *bar()*
1169 ```rust
1170 u32
1171 ```
1172 "#]],
1173 );
1174}
1175
1176#[test]
1177fn test_hover_through_literal_string_in_macro() {
1178 check(
1179 r#"
1180macro_rules! arr { ($($tt:tt)*) => { [$($tt)*] } }
1181fn foo() {
1182 let mastered_for_itunes = "";
1183 let _ = arr!("Tr$0acks", &mastered_for_itunes);
1184}
1185"#,
1186 expect![[r#"
1187 *"Tracks"*
1188 ```rust
1189 &str
1190 ```
1191 "#]],
1192 );
1193}
1194
1195#[test]
1196fn test_hover_through_assert_macro() {
1197 check(
1198 r#"
1199#[rustc_builtin_macro]
1200macro_rules! assert {}
1201
1202fn bar() -> bool { true }
1203fn foo() {
1204 assert!(ba$0r());
1205}
1206"#,
1207 expect![[r#"
1208 *bar*
1209
1210 ```rust
1211 test
1212 ```
1213
1214 ```rust
1215 fn bar() -> bool
1216 ```
1217 "#]],
1218 );
1219}
1220
1221#[test]
1222fn test_hover_multiple_actions() {
1223 check_actions(
1224 r#"
1225struct Bar;
1226struct Foo { bar: Bar }
1227
1228fn foo(Foo { b$0ar }: &Foo) {}
1229 "#,
1230 expect![[r#"
1231 [
1232 GoToType(
1233 [
1234 HoverGotoTypeData {
1235 mod_path: "test::Bar",
1236 nav: NavigationTarget {
1237 file_id: FileId(
1238 0,
1239 ),
1240 full_range: 0..11,
1241 focus_range: 7..10,
1242 name: "Bar",
1243 kind: Struct,
1244 description: "struct Bar",
1245 },
1246 },
1247 ],
1248 ),
1249 ]
1250 "#]],
1251 )
1252}
1253
1254#[test]
1255fn test_hover_through_literal_string_in_builtin_macro() {
1256 check_hover_no_result(
1257 r#"
1258 #[rustc_builtin_macro]
1259 macro_rules! format {}
1260
1261 fn foo() {
1262 format!("hel$0lo {}", 0);
1263 }
1264"#,
1265 );
1266}
1267
1268#[test]
1269fn test_hover_non_ascii_space_doc() {
1270 check(
1271 "
1272/// <- `\u{3000}` here
1273fn foo() { }
1274
1275fn bar() { fo$0o(); }
1276",
1277 expect![[r#"
1278 *foo*
1279
1280 ```rust
1281 test
1282 ```
1283
1284 ```rust
1285 fn foo()
1286 ```
1287
1288 ---
1289
1290 \<- ` ` here
1291 "#]],
1292 );
1293}
1294
1295#[test]
1296fn test_hover_function_show_qualifiers() {
1297 check(
1298 r#"async fn foo$0() {}"#,
1299 expect![[r#"
1300 *foo*
1301
1302 ```rust
1303 test
1304 ```
1305
1306 ```rust
1307 async fn foo()
1308 ```
1309 "#]],
1310 );
1311 check(
1312 r#"pub const unsafe fn foo$0() {}"#,
1313 expect![[r#"
1314 *foo*
1315
1316 ```rust
1317 test
1318 ```
1319
1320 ```rust
1321 pub const unsafe fn foo()
1322 ```
1323 "#]],
1324 );
1325 // Top level `pub(crate)` will be displayed as no visibility.
1326 check(
1327 r#"mod m { pub(crate) async unsafe extern "C" fn foo$0() {} }"#,
1328 expect![[r#"
1329 *foo*
1330
1331 ```rust
1332 test::m
1333 ```
1334
1335 ```rust
1336 pub(crate) async unsafe extern "C" fn foo()
1337 ```
1338 "#]],
1339 );
1340}
1341
1342#[test]
1343fn test_hover_function_show_types() {
1344 check(
1345 r#"fn foo$0(a: i32, b:i32) -> i32 { 0 }"#,
1346 expect![[r#"
1347 *foo*
1348
1349 ```rust
1350 test
1351 ```
1352
1353 ```rust
1354 fn foo(a: i32, b: i32) -> i32
1355 ```
1356 "#]],
1357 );
1358}
1359
1360#[test]
1361fn test_hover_function_pointer_show_identifiers() {
1362 check(
1363 r#"type foo$0 = fn(a: i32, b: i32) -> i32;"#,
1364 expect![[r#"
1365 *foo*
1366
1367 ```rust
1368 test
1369 ```
1370
1371 ```rust
1372 type foo = fn(a: i32, b: i32) -> i32
1373 ```
1374 "#]],
1375 );
1376}
1377
1378#[test]
1379fn test_hover_function_pointer_no_identifier() {
1380 check(
1381 r#"type foo$0 = fn(i32, _: i32) -> i32;"#,
1382 expect![[r#"
1383 *foo*
1384
1385 ```rust
1386 test
1387 ```
1388
1389 ```rust
1390 type foo = fn(i32, i32) -> i32
1391 ```
1392 "#]],
1393 );
1394}
1395
1396#[test]
1397fn test_hover_trait_show_qualifiers() {
1398 check_actions(
1399 r"unsafe trait foo$0() {}",
1400 expect![[r#"
1401 [
1402 Implementation(
1403 FilePosition {
1404 file_id: FileId(
1405 0,
1406 ),
1407 offset: 13,
1408 },
1409 ),
1410 ]
1411 "#]],
1412 );
1413}
1414
1415#[test]
1416fn test_hover_extern_crate() {
1417 check(
1418 r#"
1419//- /main.rs crate:main deps:std
1420extern crate st$0d;
1421//- /std/lib.rs crate:std
1422//! Standard library for this test
1423//!
1424//! Printed?
1425//! abc123
1426"#,
1427 expect![[r#"
1428 *std*
1429
1430 ```rust
1431 extern crate std
1432 ```
1433
1434 ---
1435
1436 Standard library for this test
1437
1438 Printed?
1439 abc123
1440 "#]],
1441 );
1442 check(
1443 r#"
1444//- /main.rs crate:main deps:std
1445extern crate std as ab$0c;
1446//- /std/lib.rs crate:std
1447//! Standard library for this test
1448//!
1449//! Printed?
1450//! abc123
1451"#,
1452 expect![[r#"
1453 *abc*
1454
1455 ```rust
1456 extern crate std
1457 ```
1458
1459 ---
1460
1461 Standard library for this test
1462
1463 Printed?
1464 abc123
1465 "#]],
1466 );
1467}
1468
1469#[test]
1470fn test_hover_mod_with_same_name_as_function() {
1471 check(
1472 r#"
1473use self::m$0y::Bar;
1474mod my { pub struct Bar; }
1475
1476fn my() {}
1477"#,
1478 expect![[r#"
1479 *my*
1480
1481 ```rust
1482 test
1483 ```
1484
1485 ```rust
1486 mod my
1487 ```
1488 "#]],
1489 );
1490}
1491
1492#[test]
1493fn test_hover_struct_doc_comment() {
1494 check(
1495 r#"
1496/// This is an example
1497/// multiline doc
1498///
1499/// # Example
1500///
1501/// ```
1502/// let five = 5;
1503///
1504/// assert_eq!(6, my_crate::add_one(5));
1505/// ```
1506struct Bar;
1507
1508fn foo() { let bar = Ba$0r; }
1509"#,
1510 expect![[r##"
1511 *Bar*
1512
1513 ```rust
1514 test
1515 ```
1516
1517 ```rust
1518 struct Bar
1519 ```
1520
1521 ---
1522
1523 This is an example
1524 multiline doc
1525
1526 # Example
1527
1528 ```
1529 let five = 5;
1530
1531 assert_eq!(6, my_crate::add_one(5));
1532 ```
1533 "##]],
1534 );
1535}
1536
1537#[test]
1538fn test_hover_struct_doc_attr() {
1539 check(
1540 r#"
1541#[doc = "bar docs"]
1542struct Bar;
1543
1544fn foo() { let bar = Ba$0r; }
1545"#,
1546 expect![[r#"
1547 *Bar*
1548
1549 ```rust
1550 test
1551 ```
1552
1553 ```rust
1554 struct Bar
1555 ```
1556
1557 ---
1558
1559 bar docs
1560 "#]],
1561 );
1562}
1563
1564#[test]
1565fn test_hover_struct_doc_attr_multiple_and_mixed() {
1566 check(
1567 r#"
1568/// bar docs 0
1569#[doc = "bar docs 1"]
1570#[doc = "bar docs 2"]
1571struct Bar;
1572
1573fn foo() { let bar = Ba$0r; }
1574"#,
1575 expect![[r#"
1576 *Bar*
1577
1578 ```rust
1579 test
1580 ```
1581
1582 ```rust
1583 struct Bar
1584 ```
1585
1586 ---
1587
1588 bar docs 0
1589 bar docs 1
1590 bar docs 2
1591 "#]],
1592 );
1593}
1594
1595#[test]
1596fn test_hover_external_url() {
1597 check(
1598 r#"
1599pub struct Foo;
1600/// [external](https://www.google.com)
1601pub struct B$0ar
1602"#,
1603 expect![[r#"
1604 *Bar*
1605
1606 ```rust
1607 test
1608 ```
1609
1610 ```rust
1611 pub struct Bar
1612 ```
1613
1614 ---
1615
1616 [external](https://www.google.com)
1617 "#]],
1618 );
1619}
1620
1621// Check that we don't rewrite links which we can't identify
1622#[test]
1623fn test_hover_unknown_target() {
1624 check(
1625 r#"
1626pub struct Foo;
1627/// [baz](Baz)
1628pub struct B$0ar
1629"#,
1630 expect![[r#"
1631 *Bar*
1632
1633 ```rust
1634 test
1635 ```
1636
1637 ```rust
1638 pub struct Bar
1639 ```
1640
1641 ---
1642
1643 [baz](Baz)
1644 "#]],
1645 );
1646}
1647
1648#[test]
1649fn test_hover_no_links() {
1650 check_hover_no_links(
1651 r#"
1652/// Test cases:
1653/// case 1. bare URL: https://www.example.com/
1654/// case 2. inline URL with title: [example](https://www.example.com/)
1655/// case 3. code reference: [`Result`]
1656/// case 4. code reference but miss footnote: [`String`]
1657/// case 5. autolink: <http://www.example.com/>
1658/// case 6. email address: <test@example.com>
1659/// case 7. reference: [example][example]
1660/// case 8. collapsed link: [example][]
1661/// case 9. shortcut link: [example]
1662/// case 10. inline without URL: [example]()
1663/// case 11. reference: [foo][foo]
1664/// case 12. reference: [foo][bar]
1665/// case 13. collapsed link: [foo][]
1666/// case 14. shortcut link: [foo]
1667/// case 15. inline without URL: [foo]()
1668/// case 16. just escaped text: \[foo]
1669/// case 17. inline link: [Foo](foo::Foo)
1670///
1671/// [`Result`]: ../../std/result/enum.Result.html
1672/// [^example]: https://www.example.com/
1673pub fn fo$0o() {}
1674"#,
1675 expect![[r#"
1676 *foo*
1677
1678 ```rust
1679 test
1680 ```
1681
1682 ```rust
1683 pub fn foo()
1684 ```
1685
1686 ---
1687
1688 Test cases:
1689 case 1. bare URL: https://www.example.com/
1690 case 2. inline URL with title: [example](https://www.example.com/)
1691 case 3. code reference: `Result`
1692 case 4. code reference but miss footnote: `String`
1693 case 5. autolink: http://www.example.com/
1694 case 6. email address: test@example.com
1695 case 7. reference: example
1696 case 8. collapsed link: example
1697 case 9. shortcut link: example
1698 case 10. inline without URL: example
1699 case 11. reference: foo
1700 case 12. reference: foo
1701 case 13. collapsed link: foo
1702 case 14. shortcut link: foo
1703 case 15. inline without URL: foo
1704 case 16. just escaped text: \[foo\]
1705 case 17. inline link: Foo
1706
1707 [^example]: https://www.example.com/
1708 "#]],
1709 );
1710}
1711
1712#[test]
1713fn test_hover_macro_generated_struct_fn_doc_comment() {
1714 cov_mark::check!(hover_macro_generated_struct_fn_doc_comment);
1715
1716 check(
1717 r#"
1718macro_rules! bar {
1719 () => {
1720 struct Bar;
1721 impl Bar {
1722 /// Do the foo
1723 fn foo(&self) {}
1724 }
1725 }
1726}
1727
1728bar!();
1729
1730fn foo() { let bar = Bar; bar.fo$0o(); }
1731"#,
1732 expect![[r#"
1733 *foo*
1734
1735 ```rust
1736 test::Bar
1737 ```
1738
1739 ```rust
1740 fn foo(&self)
1741 ```
1742
1743 ---
1744
1745 Do the foo
1746 "#]],
1747 );
1748}
1749
1750#[test]
1751fn test_hover_macro_generated_struct_fn_doc_attr() {
1752 cov_mark::check!(hover_macro_generated_struct_fn_doc_attr);
1753
1754 check(
1755 r#"
1756macro_rules! bar {
1757 () => {
1758 struct Bar;
1759 impl Bar {
1760 #[doc = "Do the foo"]
1761 fn foo(&self) {}
1762 }
1763 }
1764}
1765
1766bar!();
1767
1768fn foo() { let bar = Bar; bar.fo$0o(); }
1769"#,
1770 expect![[r#"
1771 *foo*
1772
1773 ```rust
1774 test::Bar
1775 ```
1776
1777 ```rust
1778 fn foo(&self)
1779 ```
1780
1781 ---
1782
1783 Do the foo
1784 "#]],
1785 );
1786}
1787
1788#[test]
1789fn test_hover_variadic_function() {
1790 check(
1791 r#"
1792extern "C" {
1793 pub fn foo(bar: i32, ...) -> i32;
1794}
1795
1796fn main() { let foo_test = unsafe { fo$0o(1, 2, 3); } }
1797"#,
1798 expect![[r#"
1799 *foo*
1800
1801 ```rust
1802 test
1803 ```
1804
1805 ```rust
1806 pub unsafe fn foo(bar: i32, ...) -> i32
1807 ```
1808 "#]],
1809 );
1810}
1811
1812#[test]
1813fn test_hover_trait_has_impl_action() {
1814 check_actions(
1815 r#"trait foo$0() {}"#,
1816 expect![[r#"
1817 [
1818 Implementation(
1819 FilePosition {
1820 file_id: FileId(
1821 0,
1822 ),
1823 offset: 6,
1824 },
1825 ),
1826 ]
1827 "#]],
1828 );
1829}
1830
1831#[test]
1832fn test_hover_struct_has_impl_action() {
1833 check_actions(
1834 r"struct foo$0() {}",
1835 expect![[r#"
1836 [
1837 Implementation(
1838 FilePosition {
1839 file_id: FileId(
1840 0,
1841 ),
1842 offset: 7,
1843 },
1844 ),
1845 ]
1846 "#]],
1847 );
1848}
1849
1850#[test]
1851fn test_hover_union_has_impl_action() {
1852 check_actions(
1853 r#"union foo$0() {}"#,
1854 expect![[r#"
1855 [
1856 Implementation(
1857 FilePosition {
1858 file_id: FileId(
1859 0,
1860 ),
1861 offset: 6,
1862 },
1863 ),
1864 ]
1865 "#]],
1866 );
1867}
1868
1869#[test]
1870fn test_hover_enum_has_impl_action() {
1871 check_actions(
1872 r"enum foo$0() { A, B }",
1873 expect![[r#"
1874 [
1875 Implementation(
1876 FilePosition {
1877 file_id: FileId(
1878 0,
1879 ),
1880 offset: 5,
1881 },
1882 ),
1883 ]
1884 "#]],
1885 );
1886}
1887
1888#[test]
1889fn test_hover_self_has_impl_action() {
1890 check_actions(
1891 r#"struct foo where Self$0:;"#,
1892 expect![[r#"
1893 [
1894 Implementation(
1895 FilePosition {
1896 file_id: FileId(
1897 0,
1898 ),
1899 offset: 7,
1900 },
1901 ),
1902 ]
1903 "#]],
1904 );
1905}
1906
1907#[test]
1908fn test_hover_test_has_action() {
1909 check_actions(
1910 r#"
1911#[test]
1912fn foo_$0test() {}
1913"#,
1914 expect![[r#"
1915 [
1916 Reference(
1917 FilePosition {
1918 file_id: FileId(
1919 0,
1920 ),
1921 offset: 11,
1922 },
1923 ),
1924 Runnable(
1925 Runnable {
1926 use_name_in_title: false,
1927 nav: NavigationTarget {
1928 file_id: FileId(
1929 0,
1930 ),
1931 full_range: 0..24,
1932 focus_range: 11..19,
1933 name: "foo_test",
1934 kind: Function,
1935 },
1936 kind: Test {
1937 test_id: Path(
1938 "foo_test",
1939 ),
1940 attr: TestAttr {
1941 ignore: false,
1942 },
1943 },
1944 cfg: None,
1945 },
1946 ),
1947 ]
1948 "#]],
1949 );
1950}
1951
1952#[test]
1953fn test_hover_test_mod_has_action() {
1954 check_actions(
1955 r#"
1956mod tests$0 {
1957 #[test]
1958 fn foo_test() {}
1959}
1960"#,
1961 expect![[r#"
1962 [
1963 Runnable(
1964 Runnable {
1965 use_name_in_title: false,
1966 nav: NavigationTarget {
1967 file_id: FileId(
1968 0,
1969 ),
1970 full_range: 0..46,
1971 focus_range: 4..9,
1972 name: "tests",
1973 kind: Module,
1974 description: "mod tests",
1975 },
1976 kind: TestMod {
1977 path: "tests",
1978 },
1979 cfg: None,
1980 },
1981 ),
1982 ]
1983 "#]],
1984 );
1985}
1986
1987#[test]
1988fn test_hover_struct_has_goto_type_action() {
1989 check_actions(
1990 r#"
1991struct S{ f1: u32 }
1992
1993fn main() { let s$0t = S{ f1:0 }; }
1994"#,
1995 expect![[r#"
1996 [
1997 GoToType(
1998 [
1999 HoverGotoTypeData {
2000 mod_path: "test::S",
2001 nav: NavigationTarget {
2002 file_id: FileId(
2003 0,
2004 ),
2005 full_range: 0..19,
2006 focus_range: 7..8,
2007 name: "S",
2008 kind: Struct,
2009 description: "struct S",
2010 },
2011 },
2012 ],
2013 ),
2014 ]
2015 "#]],
2016 );
2017}
2018
2019#[test]
2020fn test_hover_generic_struct_has_goto_type_actions() {
2021 check_actions(
2022 r#"
2023struct Arg(u32);
2024struct S<T>{ f1: T }
2025
2026fn main() { let s$0t = S{ f1:Arg(0) }; }
2027"#,
2028 expect![[r#"
2029 [
2030 GoToType(
2031 [
2032 HoverGotoTypeData {
2033 mod_path: "test::S",
2034 nav: NavigationTarget {
2035 file_id: FileId(
2036 0,
2037 ),
2038 full_range: 17..37,
2039 focus_range: 24..25,
2040 name: "S",
2041 kind: Struct,
2042 description: "struct S<T>",
2043 },
2044 },
2045 HoverGotoTypeData {
2046 mod_path: "test::Arg",
2047 nav: NavigationTarget {
2048 file_id: FileId(
2049 0,
2050 ),
2051 full_range: 0..16,
2052 focus_range: 7..10,
2053 name: "Arg",
2054 kind: Struct,
2055 description: "struct Arg",
2056 },
2057 },
2058 ],
2059 ),
2060 ]
2061 "#]],
2062 );
2063}
2064
2065#[test]
2066fn test_hover_generic_struct_has_flattened_goto_type_actions() {
2067 check_actions(
2068 r#"
2069struct Arg(u32);
2070struct S<T>{ f1: T }
2071
2072fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
2073"#,
2074 expect![[r#"
2075 [
2076 GoToType(
2077 [
2078 HoverGotoTypeData {
2079 mod_path: "test::S",
2080 nav: NavigationTarget {
2081 file_id: FileId(
2082 0,
2083 ),
2084 full_range: 17..37,
2085 focus_range: 24..25,
2086 name: "S",
2087 kind: Struct,
2088 description: "struct S<T>",
2089 },
2090 },
2091 HoverGotoTypeData {
2092 mod_path: "test::Arg",
2093 nav: NavigationTarget {
2094 file_id: FileId(
2095 0,
2096 ),
2097 full_range: 0..16,
2098 focus_range: 7..10,
2099 name: "Arg",
2100 kind: Struct,
2101 description: "struct Arg",
2102 },
2103 },
2104 ],
2105 ),
2106 ]
2107 "#]],
2108 );
2109}
2110
2111#[test]
2112fn test_hover_tuple_has_goto_type_actions() {
2113 check_actions(
2114 r#"
2115struct A(u32);
2116struct B(u32);
2117mod M {
2118 pub struct C(u32);
2119}
2120
2121fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
2122"#,
2123 expect![[r#"
2124 [
2125 GoToType(
2126 [
2127 HoverGotoTypeData {
2128 mod_path: "test::A",
2129 nav: NavigationTarget {
2130 file_id: FileId(
2131 0,
2132 ),
2133 full_range: 0..14,
2134 focus_range: 7..8,
2135 name: "A",
2136 kind: Struct,
2137 description: "struct A",
2138 },
2139 },
2140 HoverGotoTypeData {
2141 mod_path: "test::B",
2142 nav: NavigationTarget {
2143 file_id: FileId(
2144 0,
2145 ),
2146 full_range: 15..29,
2147 focus_range: 22..23,
2148 name: "B",
2149 kind: Struct,
2150 description: "struct B",
2151 },
2152 },
2153 HoverGotoTypeData {
2154 mod_path: "test::M::C",
2155 nav: NavigationTarget {
2156 file_id: FileId(
2157 0,
2158 ),
2159 full_range: 42..60,
2160 focus_range: 53..54,
2161 name: "C",
2162 kind: Struct,
2163 description: "pub struct C",
2164 },
2165 },
2166 ],
2167 ),
2168 ]
2169 "#]],
2170 );
2171}
2172
2173#[test]
2174fn test_hover_return_impl_trait_has_goto_type_action() {
2175 check_actions(
2176 r#"
2177trait Foo {}
2178fn foo() -> impl Foo {}
2179
2180fn main() { let s$0t = foo(); }
2181"#,
2182 expect![[r#"
2183 [
2184 GoToType(
2185 [
2186 HoverGotoTypeData {
2187 mod_path: "test::Foo",
2188 nav: NavigationTarget {
2189 file_id: FileId(
2190 0,
2191 ),
2192 full_range: 0..12,
2193 focus_range: 6..9,
2194 name: "Foo",
2195 kind: Trait,
2196 description: "trait Foo",
2197 },
2198 },
2199 ],
2200 ),
2201 ]
2202 "#]],
2203 );
2204}
2205
2206#[test]
2207fn test_hover_generic_return_impl_trait_has_goto_type_action() {
2208 check_actions(
2209 r#"
2210trait Foo<T> {}
2211struct S;
2212fn foo() -> impl Foo<S> {}
2213
2214fn main() { let s$0t = foo(); }
2215"#,
2216 expect![[r#"
2217 [
2218 GoToType(
2219 [
2220 HoverGotoTypeData {
2221 mod_path: "test::Foo",
2222 nav: NavigationTarget {
2223 file_id: FileId(
2224 0,
2225 ),
2226 full_range: 0..15,
2227 focus_range: 6..9,
2228 name: "Foo",
2229 kind: Trait,
2230 description: "trait Foo<T>",
2231 },
2232 },
2233 HoverGotoTypeData {
2234 mod_path: "test::S",
2235 nav: NavigationTarget {
2236 file_id: FileId(
2237 0,
2238 ),
2239 full_range: 16..25,
2240 focus_range: 23..24,
2241 name: "S",
2242 kind: Struct,
2243 description: "struct S",
2244 },
2245 },
2246 ],
2247 ),
2248 ]
2249 "#]],
2250 );
2251}
2252
2253#[test]
2254fn test_hover_return_impl_traits_has_goto_type_action() {
2255 check_actions(
2256 r#"
2257trait Foo {}
2258trait Bar {}
2259fn foo() -> impl Foo + Bar {}
2260
2261fn main() { let s$0t = foo(); }
2262"#,
2263 expect![[r#"
2264 [
2265 GoToType(
2266 [
2267 HoverGotoTypeData {
2268 mod_path: "test::Foo",
2269 nav: NavigationTarget {
2270 file_id: FileId(
2271 0,
2272 ),
2273 full_range: 0..12,
2274 focus_range: 6..9,
2275 name: "Foo",
2276 kind: Trait,
2277 description: "trait Foo",
2278 },
2279 },
2280 HoverGotoTypeData {
2281 mod_path: "test::Bar",
2282 nav: NavigationTarget {
2283 file_id: FileId(
2284 0,
2285 ),
2286 full_range: 13..25,
2287 focus_range: 19..22,
2288 name: "Bar",
2289 kind: Trait,
2290 description: "trait Bar",
2291 },
2292 },
2293 ],
2294 ),
2295 ]
2296 "#]],
2297 );
2298}
2299
2300#[test]
2301fn test_hover_generic_return_impl_traits_has_goto_type_action() {
2302 check_actions(
2303 r#"
2304trait Foo<T> {}
2305trait Bar<T> {}
2306struct S1 {}
2307struct S2 {}
2308
2309fn foo() -> impl Foo<S1> + Bar<S2> {}
2310
2311fn main() { let s$0t = foo(); }
2312"#,
2313 expect![[r#"
2314 [
2315 GoToType(
2316 [
2317 HoverGotoTypeData {
2318 mod_path: "test::Foo",
2319 nav: NavigationTarget {
2320 file_id: FileId(
2321 0,
2322 ),
2323 full_range: 0..15,
2324 focus_range: 6..9,
2325 name: "Foo",
2326 kind: Trait,
2327 description: "trait Foo<T>",
2328 },
2329 },
2330 HoverGotoTypeData {
2331 mod_path: "test::Bar",
2332 nav: NavigationTarget {
2333 file_id: FileId(
2334 0,
2335 ),
2336 full_range: 16..31,
2337 focus_range: 22..25,
2338 name: "Bar",
2339 kind: Trait,
2340 description: "trait Bar<T>",
2341 },
2342 },
2343 HoverGotoTypeData {
2344 mod_path: "test::S1",
2345 nav: NavigationTarget {
2346 file_id: FileId(
2347 0,
2348 ),
2349 full_range: 32..44,
2350 focus_range: 39..41,
2351 name: "S1",
2352 kind: Struct,
2353 description: "struct S1",
2354 },
2355 },
2356 HoverGotoTypeData {
2357 mod_path: "test::S2",
2358 nav: NavigationTarget {
2359 file_id: FileId(
2360 0,
2361 ),
2362 full_range: 45..57,
2363 focus_range: 52..54,
2364 name: "S2",
2365 kind: Struct,
2366 description: "struct S2",
2367 },
2368 },
2369 ],
2370 ),
2371 ]
2372 "#]],
2373 );
2374}
2375
2376#[test]
2377fn test_hover_arg_impl_trait_has_goto_type_action() {
2378 check_actions(
2379 r#"
2380trait Foo {}
2381fn foo(ar$0g: &impl Foo) {}
2382"#,
2383 expect![[r#"
2384 [
2385 GoToType(
2386 [
2387 HoverGotoTypeData {
2388 mod_path: "test::Foo",
2389 nav: NavigationTarget {
2390 file_id: FileId(
2391 0,
2392 ),
2393 full_range: 0..12,
2394 focus_range: 6..9,
2395 name: "Foo",
2396 kind: Trait,
2397 description: "trait Foo",
2398 },
2399 },
2400 ],
2401 ),
2402 ]
2403 "#]],
2404 );
2405}
2406
2407#[test]
2408fn test_hover_arg_impl_traits_has_goto_type_action() {
2409 check_actions(
2410 r#"
2411trait Foo {}
2412trait Bar<T> {}
2413struct S{}
2414
2415fn foo(ar$0g: &impl Foo + Bar<S>) {}
2416"#,
2417 expect![[r#"
2418 [
2419 GoToType(
2420 [
2421 HoverGotoTypeData {
2422 mod_path: "test::Foo",
2423 nav: NavigationTarget {
2424 file_id: FileId(
2425 0,
2426 ),
2427 full_range: 0..12,
2428 focus_range: 6..9,
2429 name: "Foo",
2430 kind: Trait,
2431 description: "trait Foo",
2432 },
2433 },
2434 HoverGotoTypeData {
2435 mod_path: "test::Bar",
2436 nav: NavigationTarget {
2437 file_id: FileId(
2438 0,
2439 ),
2440 full_range: 13..28,
2441 focus_range: 19..22,
2442 name: "Bar",
2443 kind: Trait,
2444 description: "trait Bar<T>",
2445 },
2446 },
2447 HoverGotoTypeData {
2448 mod_path: "test::S",
2449 nav: NavigationTarget {
2450 file_id: FileId(
2451 0,
2452 ),
2453 full_range: 29..39,
2454 focus_range: 36..37,
2455 name: "S",
2456 kind: Struct,
2457 description: "struct S",
2458 },
2459 },
2460 ],
2461 ),
2462 ]
2463 "#]],
2464 );
2465}
2466
2467#[test]
2468fn test_hover_async_block_impl_trait_has_goto_type_action() {
2469 check_actions(
2470 r#"
2471//- /main.rs crate:main deps:core
2472// we don't use minicore here so that this test doesn't randomly fail
2473// when someone edits minicore
2474struct S;
2475fn foo() {
2476 let fo$0o = async { S };
2477}
2478//- /core.rs crate:core
2479pub mod future {
2480 #[lang = "future_trait"]
2481 pub trait Future {}
2482}
2483"#,
2484 expect![[r#"
2485 [
2486 GoToType(
2487 [
2488 HoverGotoTypeData {
2489 mod_path: "core::future::Future",
2490 nav: NavigationTarget {
2491 file_id: FileId(
2492 1,
2493 ),
2494 full_range: 21..69,
2495 focus_range: 60..66,
2496 name: "Future",
2497 kind: Trait,
2498 description: "pub trait Future",
2499 },
2500 },
2501 HoverGotoTypeData {
2502 mod_path: "main::S",
2503 nav: NavigationTarget {
2504 file_id: FileId(
2505 0,
2506 ),
2507 full_range: 0..110,
2508 focus_range: 108..109,
2509 name: "S",
2510 kind: Struct,
2511 description: "struct S",
2512 },
2513 },
2514 ],
2515 ),
2516 ]
2517 "#]],
2518 );
2519}
2520
2521#[test]
2522fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
2523 check_actions(
2524 r#"
2525trait Foo<T> {}
2526struct S {}
2527fn foo(ar$0g: &impl Foo<S>) {}
2528"#,
2529 expect![[r#"
2530 [
2531 GoToType(
2532 [
2533 HoverGotoTypeData {
2534 mod_path: "test::Foo",
2535 nav: NavigationTarget {
2536 file_id: FileId(
2537 0,
2538 ),
2539 full_range: 0..15,
2540 focus_range: 6..9,
2541 name: "Foo",
2542 kind: Trait,
2543 description: "trait Foo<T>",
2544 },
2545 },
2546 HoverGotoTypeData {
2547 mod_path: "test::S",
2548 nav: NavigationTarget {
2549 file_id: FileId(
2550 0,
2551 ),
2552 full_range: 16..27,
2553 focus_range: 23..24,
2554 name: "S",
2555 kind: Struct,
2556 description: "struct S",
2557 },
2558 },
2559 ],
2560 ),
2561 ]
2562 "#]],
2563 );
2564}
2565
2566#[test]
2567fn test_hover_dyn_return_has_goto_type_action() {
2568 check_actions(
2569 r#"
2570trait Foo {}
2571struct S;
2572impl Foo for S {}
2573
2574struct B<T>{}
2575fn foo() -> B<dyn Foo> {}
2576
2577fn main() { let s$0t = foo(); }
2578"#,
2579 expect![[r#"
2580 [
2581 GoToType(
2582 [
2583 HoverGotoTypeData {
2584 mod_path: "test::B",
2585 nav: NavigationTarget {
2586 file_id: FileId(
2587 0,
2588 ),
2589 full_range: 42..55,
2590 focus_range: 49..50,
2591 name: "B",
2592 kind: Struct,
2593 description: "struct B<T>",
2594 },
2595 },
2596 HoverGotoTypeData {
2597 mod_path: "test::Foo",
2598 nav: NavigationTarget {
2599 file_id: FileId(
2600 0,
2601 ),
2602 full_range: 0..12,
2603 focus_range: 6..9,
2604 name: "Foo",
2605 kind: Trait,
2606 description: "trait Foo",
2607 },
2608 },
2609 ],
2610 ),
2611 ]
2612 "#]],
2613 );
2614}
2615
2616#[test]
2617fn test_hover_dyn_arg_has_goto_type_action() {
2618 check_actions(
2619 r#"
2620trait Foo {}
2621fn foo(ar$0g: &dyn Foo) {}
2622"#,
2623 expect![[r#"
2624 [
2625 GoToType(
2626 [
2627 HoverGotoTypeData {
2628 mod_path: "test::Foo",
2629 nav: NavigationTarget {
2630 file_id: FileId(
2631 0,
2632 ),
2633 full_range: 0..12,
2634 focus_range: 6..9,
2635 name: "Foo",
2636 kind: Trait,
2637 description: "trait Foo",
2638 },
2639 },
2640 ],
2641 ),
2642 ]
2643 "#]],
2644 );
2645}
2646
2647#[test]
2648fn test_hover_generic_dyn_arg_has_goto_type_action() {
2649 check_actions(
2650 r#"
2651trait Foo<T> {}
2652struct S {}
2653fn foo(ar$0g: &dyn Foo<S>) {}
2654"#,
2655 expect![[r#"
2656 [
2657 GoToType(
2658 [
2659 HoverGotoTypeData {
2660 mod_path: "test::Foo",
2661 nav: NavigationTarget {
2662 file_id: FileId(
2663 0,
2664 ),
2665 full_range: 0..15,
2666 focus_range: 6..9,
2667 name: "Foo",
2668 kind: Trait,
2669 description: "trait Foo<T>",
2670 },
2671 },
2672 HoverGotoTypeData {
2673 mod_path: "test::S",
2674 nav: NavigationTarget {
2675 file_id: FileId(
2676 0,
2677 ),
2678 full_range: 16..27,
2679 focus_range: 23..24,
2680 name: "S",
2681 kind: Struct,
2682 description: "struct S",
2683 },
2684 },
2685 ],
2686 ),
2687 ]
2688 "#]],
2689 );
2690}
2691
2692#[test]
2693fn test_hover_goto_type_action_links_order() {
2694 check_actions(
2695 r#"
2696trait ImplTrait<T> {}
2697trait DynTrait<T> {}
2698struct B<T> {}
2699struct S {}
2700
2701fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
2702"#,
2703 expect![[r#"
2704 [
2705 GoToType(
2706 [
2707 HoverGotoTypeData {
2708 mod_path: "test::ImplTrait",
2709 nav: NavigationTarget {
2710 file_id: FileId(
2711 0,
2712 ),
2713 full_range: 0..21,
2714 focus_range: 6..15,
2715 name: "ImplTrait",
2716 kind: Trait,
2717 description: "trait ImplTrait<T>",
2718 },
2719 },
2720 HoverGotoTypeData {
2721 mod_path: "test::B",
2722 nav: NavigationTarget {
2723 file_id: FileId(
2724 0,
2725 ),
2726 full_range: 43..57,
2727 focus_range: 50..51,
2728 name: "B",
2729 kind: Struct,
2730 description: "struct B<T>",
2731 },
2732 },
2733 HoverGotoTypeData {
2734 mod_path: "test::DynTrait",
2735 nav: NavigationTarget {
2736 file_id: FileId(
2737 0,
2738 ),
2739 full_range: 22..42,
2740 focus_range: 28..36,
2741 name: "DynTrait",
2742 kind: Trait,
2743 description: "trait DynTrait<T>",
2744 },
2745 },
2746 HoverGotoTypeData {
2747 mod_path: "test::S",
2748 nav: NavigationTarget {
2749 file_id: FileId(
2750 0,
2751 ),
2752 full_range: 58..69,
2753 focus_range: 65..66,
2754 name: "S",
2755 kind: Struct,
2756 description: "struct S",
2757 },
2758 },
2759 ],
2760 ),
2761 ]
2762 "#]],
2763 );
2764}
2765
2766#[test]
2767fn test_hover_associated_type_has_goto_type_action() {
2768 check_actions(
2769 r#"
2770trait Foo {
2771 type Item;
2772 fn get(self) -> Self::Item {}
2773}
2774
2775struct Bar{}
2776struct S{}
2777
2778impl Foo for S { type Item = Bar; }
2779
2780fn test() -> impl Foo { S {} }
2781
2782fn main() { let s$0t = test().get(); }
2783"#,
2784 expect![[r#"
2785 [
2786 GoToType(
2787 [
2788 HoverGotoTypeData {
2789 mod_path: "test::Foo",
2790 nav: NavigationTarget {
2791 file_id: FileId(
2792 0,
2793 ),
2794 full_range: 0..62,
2795 focus_range: 6..9,
2796 name: "Foo",
2797 kind: Trait,
2798 description: "trait Foo",
2799 },
2800 },
2801 ],
2802 ),
2803 ]
2804 "#]],
2805 );
2806}
2807
2808#[test]
2809fn test_hover_const_param_has_goto_type_action() {
2810 check_actions(
2811 r#"
2812struct Bar;
2813struct Foo<const BAR: Bar>;
2814
2815impl<const BAR: Bar> Foo<BAR$0> {}
2816"#,
2817 expect![[r#"
2818 [
2819 GoToType(
2820 [
2821 HoverGotoTypeData {
2822 mod_path: "test::Bar",
2823 nav: NavigationTarget {
2824 file_id: FileId(
2825 0,
2826 ),
2827 full_range: 0..11,
2828 focus_range: 7..10,
2829 name: "Bar",
2830 kind: Struct,
2831 description: "struct Bar",
2832 },
2833 },
2834 ],
2835 ),
2836 ]
2837 "#]],
2838 );
2839}
2840
2841#[test]
2842fn test_hover_type_param_has_goto_type_action() {
2843 check_actions(
2844 r#"
2845trait Foo {}
2846
2847fn foo<T: Foo>(t: T$0){}
2848"#,
2849 expect![[r#"
2850 [
2851 GoToType(
2852 [
2853 HoverGotoTypeData {
2854 mod_path: "test::Foo",
2855 nav: NavigationTarget {
2856 file_id: FileId(
2857 0,
2858 ),
2859 full_range: 0..12,
2860 focus_range: 6..9,
2861 name: "Foo",
2862 kind: Trait,
2863 description: "trait Foo",
2864 },
2865 },
2866 ],
2867 ),
2868 ]
2869 "#]],
2870 );
2871}
2872
2873#[test]
2874fn test_hover_self_has_go_to_type() {
2875 check_actions(
2876 r#"
2877struct Foo;
2878impl Foo {
2879 fn foo(&self$0) {}
2880}
2881"#,
2882 expect![[r#"
2883 [
2884 GoToType(
2885 [
2886 HoverGotoTypeData {
2887 mod_path: "test::Foo",
2888 nav: NavigationTarget {
2889 file_id: FileId(
2890 0,
2891 ),
2892 full_range: 0..11,
2893 focus_range: 7..10,
2894 name: "Foo",
2895 kind: Struct,
2896 description: "struct Foo",
2897 },
2898 },
2899 ],
2900 ),
2901 ]
2902 "#]],
2903 );
2904}
2905
2906#[test]
2907fn hover_displays_normalized_crate_names() {
2908 check(
2909 r#"
2910//- /lib.rs crate:name-with-dashes
2911pub mod wrapper {
2912 pub struct Thing { x: u32 }
2913
2914 impl Thing {
2915 pub fn new() -> Thing { Thing { x: 0 } }
2916 }
2917}
2918
2919//- /main.rs crate:main deps:name-with-dashes
2920fn main() { let foo_test = name_with_dashes::wrapper::Thing::new$0(); }
2921"#,
2922 expect![[r#"
2923 *new*
2924
2925 ```rust
2926 name_with_dashes::wrapper::Thing
2927 ```
2928
2929 ```rust
2930 pub fn new() -> Thing
2931 ```
2932 "#]],
2933 )
2934}
2935
2936#[test]
2937fn hover_field_pat_shorthand_ref_match_ergonomics() {
2938 check(
2939 r#"
2940struct S {
2941 f: i32,
2942}
2943
2944fn main() {
2945 let s = S { f: 0 };
2946 let S { f$0 } = &s;
2947}
2948"#,
2949 expect![[r#"
2950 *f*
2951
2952 ```rust
2953 f: &i32
2954 ```
2955 ---
2956
2957 ```rust
2958 test::S
2959 ```
2960
2961 ```rust
2962 f: i32
2963 ```
2964 "#]],
2965 );
2966}
2967
2968#[test]
2969fn const_generic_order() {
2970 check(
2971 r#"
2972struct Foo;
2973struct S$0T<const C: usize = 1, T = Foo>(T);
2974"#,
2975 expect![[r#"
2976 *ST*
2977
2978 ```rust
2979 test
2980 ```
2981
2982 ```rust
2983 struct ST<const C: usize, T = Foo>
2984 ```
2985 "#]],
2986 );
2987}
2988
2989#[test]
2990fn const_generic_positive_i8_literal() {
2991 check(
2992 r#"
2993struct Const<const N: i8>;
2994
2995fn main() {
2996 let v$0alue = Const::<1>;
2997}
2998"#,
2999 expect![[r#"
3000 *value*
3001
3002 ```rust
3003 let value: Const<1>
3004 ```
3005 "#]],
3006 );
3007}
3008
3009#[test]
3010fn const_generic_zero_i8_literal() {
3011 check(
3012 r#"
3013struct Const<const N: i8>;
3014
3015fn main() {
3016 let v$0alue = Const::<0>;
3017}
3018"#,
3019 expect![[r#"
3020 *value*
3021
3022 ```rust
3023 let value: Const<0>
3024 ```
3025 "#]],
3026 );
3027}
3028
3029#[test]
3030fn const_generic_negative_i8_literal() {
3031 check(
3032 r#"
3033struct Const<const N: i8>;
3034
3035fn main() {
3036 let v$0alue = Const::<-1>;
3037}
3038"#,
3039 expect![[r#"
3040 *value*
3041
3042 ```rust
3043 let value: Const<-1>
3044 ```
3045 "#]],
3046 );
3047}
3048
3049#[test]
3050fn const_generic_bool_literal() {
3051 check(
3052 r#"
3053struct Const<const F: bool>;
3054
3055fn main() {
3056 let v$0alue = Const::<true>;
3057}
3058"#,
3059 expect![[r#"
3060 *value*
3061
3062 ```rust
3063 let value: Const<true>
3064 ```
3065 "#]],
3066 );
3067}
3068
3069#[test]
3070fn const_generic_char_literal() {
3071 check(
3072 r#"
3073struct Const<const C: char>;
3074
3075fn main() {
3076 let v$0alue = Const::<'🦀'>;
3077}
3078"#,
3079 expect![[r#"
3080 *value*
3081
3082 ```rust
3083 let value: Const<'🦀'>
3084 ```
3085 "#]],
3086 );
3087}
3088
3089#[test]
3090fn hover_self_param_shows_type() {
3091 check(
3092 r#"
3093struct Foo {}
3094impl Foo {
3095 fn bar(&sel$0f) {}
3096}
3097"#,
3098 expect![[r#"
3099 *self*
3100
3101 ```rust
3102 self: &Foo
3103 ```
3104 "#]],
3105 );
3106}
3107
3108#[test]
3109fn hover_self_param_shows_type_for_arbitrary_self_type() {
3110 check(
3111 r#"
3112struct Arc<T>(T);
3113struct Foo {}
3114impl Foo {
3115 fn bar(sel$0f: Arc<Foo>) {}
3116}
3117"#,
3118 expect![[r#"
3119 *self*
3120
3121 ```rust
3122 self: Arc<Foo>
3123 ```
3124 "#]],
3125 );
3126}
3127
3128#[test]
3129fn hover_doc_outer_inner() {
3130 check(
3131 r#"
3132/// Be quick;
3133mod Foo$0 {
3134 //! time is mana
3135
3136 /// This comment belongs to the function
3137 fn foo() {}
3138}
3139"#,
3140 expect![[r#"
3141 *Foo*
3142
3143 ```rust
3144 test
3145 ```
3146
3147 ```rust
3148 mod Foo
3149 ```
3150
3151 ---
3152
3153 Be quick;
3154 time is mana
3155 "#]],
3156 );
3157}
3158
3159#[test]
3160fn hover_doc_outer_inner_attribue() {
3161 check(
3162 r#"
3163#[doc = "Be quick;"]
3164mod Foo$0 {
3165 #![doc = "time is mana"]
3166
3167 #[doc = "This comment belongs to the function"]
3168 fn foo() {}
3169}
3170"#,
3171 expect![[r#"
3172 *Foo*
3173
3174 ```rust
3175 test
3176 ```
3177
3178 ```rust
3179 mod Foo
3180 ```
3181
3182 ---
3183
3184 Be quick;
3185 time is mana
3186 "#]],
3187 );
3188}
3189
3190#[test]
3191fn hover_doc_block_style_indentend() {
3192 check(
3193 r#"
3194/**
3195 foo
3196 ```rust
3197 let x = 3;
3198 ```
3199*/
3200fn foo$0() {}
3201"#,
3202 expect![[r#"
3203 *foo*
3204
3205 ```rust
3206 test
3207 ```
3208
3209 ```rust
3210 fn foo()
3211 ```
3212
3213 ---
3214
3215 foo
3216
3217 ```rust
3218 let x = 3;
3219 ```
3220 "#]],
3221 );
3222}
3223
3224#[test]
3225fn hover_comments_dont_highlight_parent() {
3226 cov_mark::check!(no_highlight_on_comment_hover);
3227 check_hover_no_result(
3228 r#"
3229fn no_hover() {
3230 // no$0hover
3231}
3232"#,
3233 );
3234}
3235
3236#[test]
3237fn hover_label() {
3238 check(
3239 r#"
3240fn foo() {
3241 'label$0: loop {}
3242}
3243"#,
3244 expect![[r#"
3245 *'label*
3246
3247 ```rust
3248 'label
3249 ```
3250 "#]],
3251 );
3252}
3253
3254#[test]
3255fn hover_lifetime() {
3256 check(
3257 r#"fn foo<'lifetime>(_: &'lifetime$0 ()) {}"#,
3258 expect![[r#"
3259 *'lifetime*
3260
3261 ```rust
3262 'lifetime
3263 ```
3264 "#]],
3265 );
3266}
3267
3268#[test]
3269fn hover_type_param() {
3270 check(
3271 r#"
3272//- minicore: sized
3273struct Foo<T>(T);
3274trait TraitA {}
3275trait TraitB {}
3276impl<T: TraitA + TraitB> Foo<T$0> where T: Sized {}
3277"#,
3278 expect![[r#"
3279 *T*
3280
3281 ```rust
3282 T: TraitA + TraitB
3283 ```
3284 "#]],
3285 );
3286 check(
3287 r#"
3288//- minicore: sized
3289struct Foo<T>(T);
3290impl<T> Foo<T$0> {}
3291"#,
3292 expect![[r#"
3293 *T*
3294
3295 ```rust
3296 T
3297 ```
3298 "#]],
3299 );
3300 // lifetimes bounds arent being tracked yet
3301 check(
3302 r#"
3303//- minicore: sized
3304struct Foo<T>(T);
3305impl<T: 'static> Foo<T$0> {}
3306"#,
3307 expect![[r#"
3308 *T*
3309
3310 ```rust
3311 T
3312 ```
3313 "#]],
3314 );
3315}
3316
3317#[test]
3318fn hover_type_param_sized_bounds() {
3319 // implicit `: Sized` bound
3320 check(
3321 r#"
3322//- minicore: sized
3323trait Trait {}
3324struct Foo<T>(T);
3325impl<T: Trait> Foo<T$0> {}
3326"#,
3327 expect![[r#"
3328 *T*
3329
3330 ```rust
3331 T: Trait
3332 ```
3333 "#]],
3334 );
3335 check(
3336 r#"
3337//- minicore: sized
3338trait Trait {}
3339struct Foo<T>(T);
3340impl<T: Trait + ?Sized> Foo<T$0> {}
3341"#,
3342 expect![[r#"
3343 *T*
3344
3345 ```rust
3346 T: Trait + ?Sized
3347 ```
3348 "#]],
3349 );
3350}
3351
3352mod type_param_sized_bounds {
3353 use super::*;
3354
3355 #[test]
3356 fn single_implicit() {
3357 check(
3358 r#"
3359//- minicore: sized
3360fn foo<T$0>() {}
3361"#,
3362 expect![[r#"
3363 *T*
3364
3365 ```rust
3366 T
3367 ```
3368 "#]],
3369 );
3370 }
3371
3372 #[test]
3373 fn single_explicit() {
3374 check(
3375 r#"
3376//- minicore: sized
3377fn foo<T$0: Sized>() {}
3378"#,
3379 expect![[r#"
3380 *T*
3381
3382 ```rust
3383 T
3384 ```
3385 "#]],
3386 );
3387 }
3388
3389 #[test]
3390 fn single_relaxed() {
3391 check(
3392 r#"
3393//- minicore: sized
3394fn foo<T$0: ?Sized>() {}
3395"#,
3396 expect![[r#"
3397 *T*
3398
3399 ```rust
3400 T: ?Sized
3401 ```
3402 "#]],
3403 );
3404 }
3405
3406 #[test]
3407 fn multiple_implicit() {
3408 check(
3409 r#"
3410//- minicore: sized
3411trait Trait {}
3412fn foo<T$0: Trait>() {}
3413"#,
3414 expect![[r#"
3415 *T*
3416
3417 ```rust
3418 T: Trait
3419 ```
3420 "#]],
3421 );
3422 }
3423
3424 #[test]
3425 fn multiple_explicit() {
3426 check(
3427 r#"
3428//- minicore: sized
3429trait Trait {}
3430fn foo<T$0: Trait + Sized>() {}
3431"#,
3432 expect![[r#"
3433 *T*
3434
3435 ```rust
3436 T: Trait
3437 ```
3438 "#]],
3439 );
3440 }
3441
3442 #[test]
3443 fn multiple_relaxed() {
3444 check(
3445 r#"
3446//- minicore: sized
3447trait Trait {}
3448fn foo<T$0: Trait + ?Sized>() {}
3449"#,
3450 expect![[r#"
3451 *T*
3452
3453 ```rust
3454 T: Trait + ?Sized
3455 ```
3456 "#]],
3457 );
3458 }
3459
3460 #[test]
3461 fn mixed() {
3462 check(
3463 r#"
3464//- minicore: sized
3465fn foo<T$0: ?Sized + Sized + Sized>() {}
3466"#,
3467 expect![[r#"
3468 *T*
3469
3470 ```rust
3471 T
3472 ```
3473 "#]],
3474 );
3475 check(
3476 r#"
3477//- minicore: sized
3478trait Trait {}
3479fn foo<T$0: Sized + ?Sized + Sized + Trait>() {}
3480"#,
3481 expect![[r#"
3482 *T*
3483
3484 ```rust
3485 T: Trait
3486 ```
3487 "#]],
3488 );
3489 }
3490}
3491
3492#[test]
3493fn hover_const_generic_type_alias() {
3494 check(
3495 r#"
3496struct Foo<const LEN: usize>;
3497type Fo$0o2 = Foo<2>;
3498"#,
3499 expect![[r#"
3500 *Foo2*
3501
3502 ```rust
3503 test
3504 ```
3505
3506 ```rust
3507 type Foo2 = Foo<2>
3508 ```
3509 "#]],
3510 );
3511}
3512
3513#[test]
3514fn hover_const_param() {
3515 check(
3516 r#"
3517struct Foo<const LEN: usize>;
3518impl<const LEN: usize> Foo<LEN$0> {}
3519"#,
3520 expect![[r#"
3521 *LEN*
3522
3523 ```rust
3524 const LEN: usize
3525 ```
3526 "#]],
3527 );
3528}
3529
3530#[test]
3531fn hover_const_eval() {
3532 // show hex for <10
3533 check(
3534 r#"
3535/// This is a doc
3536const FOO$0: usize = 1 << 3;
3537"#,
3538 expect![[r#"
3539 *FOO*
3540
3541 ```rust
3542 test
3543 ```
3544
3545 ```rust
3546 const FOO: usize = 8
3547 ```
3548
3549 ---
3550
3551 This is a doc
3552 "#]],
3553 );
3554 // show hex for >10
3555 check(
3556 r#"
3557/// This is a doc
3558const FOO$0: usize = (1 << 3) + (1 << 2);
3559"#,
3560 expect![[r#"
3561 *FOO*
3562
3563 ```rust
3564 test
3565 ```
3566
3567 ```rust
3568 const FOO: usize = 12 (0xC)
3569 ```
3570
3571 ---
3572
3573 This is a doc
3574 "#]],
3575 );
3576 // show original body when const eval fails
3577 check(
3578 r#"
3579/// This is a doc
3580const FOO$0: usize = 2 - 3;
3581"#,
3582 expect![[r#"
3583 *FOO*
3584
3585 ```rust
3586 test
3587 ```
3588
3589 ```rust
3590 const FOO: usize = 2 - 3
3591 ```
3592
3593 ---
3594
3595 This is a doc
3596 "#]],
3597 );
3598 // don't show hex for negatives
3599 check(
3600 r#"
3601/// This is a doc
3602const FOO$0: i32 = 2 - 3;
3603"#,
3604 expect![[r#"
3605 *FOO*
3606
3607 ```rust
3608 test
3609 ```
3610
3611 ```rust
3612 const FOO: i32 = -1
3613 ```
3614
3615 ---
3616
3617 This is a doc
3618 "#]],
3619 );
3620 check(
3621 r#"
3622/// This is a doc
3623const FOO$0: &str = "bar";
3624"#,
3625 expect![[r#"
3626 *FOO*
3627
3628 ```rust
3629 test
3630 ```
3631
3632 ```rust
3633 const FOO: &str = "bar"
3634 ```
3635
3636 ---
3637
3638 This is a doc
3639 "#]],
3640 );
3641 // show char literal
3642 check(
3643 r#"
3644/// This is a doc
3645const FOO$0: char = 'a';
3646"#,
3647 expect![[r#"
3648 *FOO*
3649
3650 ```rust
3651 test
3652 ```
3653
3654 ```rust
3655 const FOO: char = 'a'
3656 ```
3657
3658 ---
3659
3660 This is a doc
3661 "#]],
3662 );
3663 // show escaped char literal
3664 check(
3665 r#"
3666/// This is a doc
3667const FOO$0: char = '\x61';
3668"#,
3669 expect![[r#"
3670 *FOO*
3671
3672 ```rust
3673 test
3674 ```
3675
3676 ```rust
3677 const FOO: char = 'a'
3678 ```
3679
3680 ---
3681
3682 This is a doc
3683 "#]],
3684 );
3685 // show byte literal
3686 check(
3687 r#"
3688/// This is a doc
3689const FOO$0: u8 = b'a';
3690"#,
3691 expect![[r#"
3692 *FOO*
3693
3694 ```rust
3695 test
3696 ```
3697
3698 ```rust
3699 const FOO: u8 = 97 (0x61)
3700 ```
3701
3702 ---
3703
3704 This is a doc
3705 "#]],
3706 );
3707 // show escaped byte literal
3708 check(
3709 r#"
3710/// This is a doc
3711const FOO$0: u8 = b'\x61';
3712"#,
3713 expect![[r#"
3714 *FOO*
3715
3716 ```rust
3717 test
3718 ```
3719
3720 ```rust
3721 const FOO: u8 = 97 (0x61)
3722 ```
3723
3724 ---
3725
3726 This is a doc
3727 "#]],
3728 );
3729 // show float literal
3730 check(
3731 r#"
3732 /// This is a doc
3733 const FOO$0: f64 = 1.0234;
3734 "#,
3735 expect![[r#"
3736 *FOO*
3737
3738 ```rust
3739 test
3740 ```
3741
3742 ```rust
3743 const FOO: f64 = 1.0234
3744 ```
3745
3746 ---
3747
3748 This is a doc
3749 "#]],
3750 );
3751 //show float typecasted from int
3752 check(
3753 r#"
3754/// This is a doc
3755const FOO$0: f32 = 1f32;
3756"#,
3757 expect![[r#"
3758 *FOO*
3759
3760 ```rust
3761 test
3762 ```
3763
3764 ```rust
3765 const FOO: f32 = 1.0
3766 ```
3767
3768 ---
3769
3770 This is a doc
3771 "#]],
3772 );
3773 //show f64 typecasted from float
3774 check(
3775 r#"
3776/// This is a doc
3777const FOO$0: f64 = 1.0f64;
3778"#,
3779 expect![[r#"
3780 *FOO*
3781
3782 ```rust
3783 test
3784 ```
3785
3786 ```rust
3787 const FOO: f64 = 1.0
3788 ```
3789
3790 ---
3791
3792 This is a doc
3793 "#]],
3794 );
3795}
3796
3797#[test]
3798fn hover_const_pat() {
3799 check(
3800 r#"
3801/// This is a doc
3802const FOO: usize = 3;
3803fn foo() {
3804 match 5 {
3805 FOO$0 => (),
3806 _ => ()
3807 }
3808}
3809"#,
3810 expect![[r#"
3811 *FOO*
3812
3813 ```rust
3814 test
3815 ```
3816
3817 ```rust
3818 const FOO: usize = 3
3819 ```
3820
3821 ---
3822
3823 This is a doc
3824 "#]],
3825 );
3826}
3827
3828#[test]
3829fn array_repeat_exp() {
3830 check(
3831 r#"
3832fn main() {
3833 let til$0e4 = [0_u32; (4 * 8 * 8) / 32];
3834}
3835 "#,
3836 expect![[r#"
3837 *tile4*
3838
3839 ```rust
3840 let tile4: [u32; 8]
3841 ```
3842 "#]],
3843 );
3844}
3845
3846#[test]
3847fn hover_mod_def() {
3848 check(
3849 r#"
3850//- /main.rs
3851mod foo$0;
3852//- /foo.rs
3853//! For the horde!
3854"#,
3855 expect![[r#"
3856 *foo*
3857
3858 ```rust
3859 test
3860 ```
3861
3862 ```rust
3863 mod foo
3864 ```
3865
3866 ---
3867
3868 For the horde!
3869 "#]],
3870 );
3871}
3872
3873#[test]
3874fn hover_self_in_use() {
3875 check(
3876 r#"
3877//! This should not appear
3878mod foo {
3879 /// But this should appear
3880 pub mod bar {}
3881}
3882use foo::bar::{self$0};
3883"#,
3884 expect![[r#"
3885 *self*
3886
3887 ```rust
3888 test::foo
3889 ```
3890
3891 ```rust
3892 mod bar
3893 ```
3894
3895 ---
3896
3897 But this should appear
3898 "#]],
3899 )
3900}
3901
3902#[test]
3903fn hover_keyword() {
3904 check(
3905 r#"
3906//- /main.rs crate:main deps:std
3907fn f() { retur$0n; }
3908//- /libstd.rs crate:std
3909/// Docs for return_keyword
3910mod return_keyword {}
3911"#,
3912 expect![[r#"
3913 *return*
3914
3915 ```rust
3916 return
3917 ```
3918
3919 ---
3920
3921 Docs for return_keyword
3922 "#]],
3923 );
3924}
3925
3926#[test]
3927fn hover_keyword_doc() {
3928 check(
3929 r#"
3930//- /main.rs crate:main deps:std
3931fn foo() {
3932 let bar = mov$0e || {};
3933}
3934//- /libstd.rs crate:std
3935#[doc(keyword = "move")]
3936/// [closure]
3937/// [closures][closure]
3938/// [threads]
3939/// <https://doc.rust-lang.org/nightly/book/ch13-01-closures.html>
3940///
3941/// [closure]: ../book/ch13-01-closures.html
3942/// [threads]: ../book/ch16-01-threads.html#using-move-closures-with-threads
3943mod move_keyword {}
3944"#,
3945 expect![[r##"
3946 *move*
3947
3948 ```rust
3949 move
3950 ```
3951
3952 ---
3953
3954 [closure](https://doc.rust-lang.org/nightly/book/ch13-01-closures.html)
3955 [closures](https://doc.rust-lang.org/nightly/book/ch13-01-closures.html)
3956 [threads](https://doc.rust-lang.org/nightly/book/ch16-01-threads.html#using-move-closures-with-threads)
3957 <https://doc.rust-lang.org/nightly/book/ch13-01-closures.html>
3958 "##]],
3959 );
3960}
3961
3962#[test]
3963fn hover_keyword_as_primitive() {
3964 check(
3965 r#"
3966//- /main.rs crate:main deps:std
3967type F = f$0n(i32) -> i32;
3968//- /libstd.rs crate:std
3969/// Docs for prim_fn
3970mod prim_fn {}
3971"#,
3972 expect![[r#"
3973 *fn*
3974
3975 ```rust
3976 fn
3977 ```
3978
3979 ---
3980
3981 Docs for prim_fn
3982 "#]],
3983 );
3984}
3985
3986#[test]
3987fn hover_builtin() {
3988 check(
3989 r#"
3990//- /main.rs crate:main deps:std
3991cosnt _: &str$0 = ""; }
3992
3993//- /libstd.rs crate:std
3994/// Docs for prim_str
3995/// [`foo`](../std/keyword.foo.html)
3996mod prim_str {}
3997"#,
3998 expect![[r#"
3999 *str*
4000
4001 ```rust
4002 str
4003 ```
4004
4005 ---
4006
4007 Docs for prim_str
4008 [`foo`](https://doc.rust-lang.org/nightly/std/keyword.foo.html)
4009 "#]],
4010 );
4011}
4012
4013#[test]
4014fn hover_macro_expanded_function() {
4015 check(
4016 r#"
4017struct S<'a, T>(&'a T);
4018trait Clone {}
4019macro_rules! foo {
4020 () => {
4021 fn bar<'t, T: Clone + 't>(s: &mut S<'t, T>, t: u32) -> *mut u32 where
4022 't: 't + 't,
4023 for<'a> T: Clone + 'a
4024 { 0 as _ }
4025 };
4026}
4027
4028foo!();
4029
4030fn main() {
4031 bar$0;
4032}
4033"#,
4034 expect![[r#"
4035 *bar*
4036
4037 ```rust
4038 test
4039 ```
4040
4041 ```rust
4042 fn bar<'t, T>(s: &mut S<'t, T>, t: u32) -> *mut u32
4043 where
4044 T: Clone + 't,
4045 't: 't + 't,
4046 for<'a> T: Clone + 'a,
4047 ```
4048 "#]],
4049 )
4050}
4051
4052#[test]
4053fn hover_intra_doc_links() {
4054 check(
4055 r#"
4056
4057pub mod theitem {
4058 /// This is the item. Cool!
4059 pub struct TheItem;
4060}
4061
4062/// Gives you a [`TheItem$0`].
4063///
4064/// [`TheItem`]: theitem::TheItem
4065pub fn gimme() -> theitem::TheItem {
4066 theitem::TheItem
4067}
4068"#,
4069 expect![[r#"
4070 *[`TheItem`]*
4071
4072 ```rust
4073 test::theitem
4074 ```
4075
4076 ```rust
4077 pub struct TheItem
4078 ```
4079
4080 ---
4081
4082 This is the item. Cool!
4083 "#]],
4084 );
4085}
4086
4087#[test]
4088fn test_hover_trait_assoc_typealias() {
4089 check(
4090 r#"
4091 fn main() {}
4092
4093trait T1 {
4094 type Bar;
4095 type Baz;
4096}
4097
4098struct Foo;
4099
4100mod t2 {
4101 pub trait T2 {
4102 type Bar;
4103 }
4104}
4105
4106use t2::T2;
4107
4108impl T2 for Foo {
4109 type Bar = String;
4110}
4111
4112impl T1 for Foo {
4113 type Bar = <Foo as t2::T2>::Ba$0r;
4114 // ^^^ unresolvedReference
4115}
4116 "#,
4117 expect![[r#"
4118*Bar*
4119
4120```rust
4121test::t2
4122```
4123
4124```rust
4125pub type Bar
4126```
4127"#]],
4128 );
4129}
4130#[test]
4131fn hover_generic_assoc() {
4132 check(
4133 r#"
4134fn foo<T: A>() where T::Assoc$0: {}
4135
4136trait A {
4137 type Assoc;
4138}"#,
4139 expect![[r#"
4140 *Assoc*
4141
4142 ```rust
4143 test
4144 ```
4145
4146 ```rust
4147 type Assoc
4148 ```
4149 "#]],
4150 );
4151 check(
4152 r#"
4153fn foo<T: A>() {
4154 let _: <T>::Assoc$0;
4155}
4156
4157trait A {
4158 type Assoc;
4159}"#,
4160 expect![[r#"
4161 *Assoc*
4162
4163 ```rust
4164 test
4165 ```
4166
4167 ```rust
4168 type Assoc
4169 ```
4170 "#]],
4171 );
4172 check(
4173 r#"
4174trait A where
4175 Self::Assoc$0: ,
4176{
4177 type Assoc;
4178}"#,
4179 expect![[r#"
4180 *Assoc*
4181
4182 ```rust
4183 test
4184 ```
4185
4186 ```rust
4187 type Assoc
4188 ```
4189 "#]],
4190 );
4191}
4192
4193#[test]
4194fn string_shadowed_with_inner_items() {
4195 check(
4196 r#"
4197//- /main.rs crate:main deps:alloc
4198
4199/// Custom `String` type.
4200struct String;
4201
4202fn f() {
4203 let _: String$0;
4204
4205 fn inner() {}
4206}
4207
4208//- /alloc.rs crate:alloc
4209#[prelude_import]
4210pub use string::*;
4211
4212mod string {
4213 /// This is `alloc::String`.
4214 pub struct String;
4215}
4216"#,
4217 expect![[r#"
4218 *String*
4219
4220 ```rust
4221 main
4222 ```
4223
4224 ```rust
4225 struct String
4226 ```
4227
4228 ---
4229
4230 Custom `String` type.
4231 "#]],
4232 )
4233}
4234
4235#[test]
4236fn function_doesnt_shadow_crate_in_use_tree() {
4237 check(
4238 r#"
4239//- /main.rs crate:main deps:foo
4240use foo$0::{foo};
4241
4242//- /foo.rs crate:foo
4243pub fn foo() {}
4244"#,
4245 expect![[r#"
4246 *foo*
4247
4248 ```rust
4249 extern crate foo
4250 ```
4251 "#]],
4252 )
4253}
4254
4255#[test]
4256fn hover_feature() {
4257 check(
4258 r#"#![feature(box_syntax$0)]"#,
4259 expect![[r##"
4260 *box_syntax*
4261 ```
4262 box_syntax
4263 ```
4264 ___
4265
4266 # `box_syntax`
4267
4268 The tracking issue for this feature is: [#49733]
4269
4270 [#49733]: https://github.com/rust-lang/rust/issues/49733
4271
4272 See also [`box_patterns`](box-patterns.md)
4273
4274 ------------------------
4275
4276 Currently the only stable way to create a `Box` is via the `Box::new` method.
4277 Also it is not possible in stable Rust to destructure a `Box` in a match
4278 pattern. The unstable `box` keyword can be used to create a `Box`. An example
4279 usage would be:
4280
4281 ```rust
4282 #![feature(box_syntax)]
4283
4284 fn main() {
4285 let b = box 5;
4286 }
4287 ```
4288
4289 "##]],
4290 )
4291}
4292
4293#[test]
4294fn hover_lint() {
4295 check(
4296 r#"#![allow(arithmetic_overflow$0)]"#,
4297 expect![[r#"
4298 *arithmetic_overflow*
4299 ```
4300 arithmetic_overflow
4301 ```
4302 ___
4303
4304 arithmetic operation overflows
4305 "#]],
4306 )
4307}
4308
4309#[test]
4310fn hover_clippy_lint() {
4311 check(
4312 r#"#![allow(clippy::almost_swapped$0)]"#,
4313 expect![[r#"
4314 *almost_swapped*
4315 ```
4316 clippy::almost_swapped
4317 ```
4318 ___
4319
4320 Checks for `foo = bar; bar = foo` sequences.
4321 "#]],
4322 )
4323}
4324
4325#[test]
4326fn hover_attr_path_qualifier() {
4327 check(
4328 r#"
4329//- /foo.rs crate:foo
4330
4331//- /lib.rs crate:main.rs deps:foo
4332#[fo$0o::bar()]
4333struct Foo;
4334"#,
4335 expect![[r#"
4336 *foo*
4337
4338 ```rust
4339 extern crate foo
4340 ```
4341 "#]],
4342 )
4343}
4344
4345#[test]
4346fn hover_rename() {
4347 check(
4348 r#"
4349use self as foo$0;
4350"#,
4351 expect![[r#"
4352 *foo*
4353
4354 ```rust
4355 extern crate test
4356 ```
4357 "#]],
4358 );
4359 check(
4360 r#"
4361mod bar {}
4362use bar::{self as foo$0};
4363"#,
4364 expect![[r#"
4365 *foo*
4366
4367 ```rust
4368 test
4369 ```
4370
4371 ```rust
4372 mod bar
4373 ```
4374 "#]],
4375 );
4376 check(
4377 r#"
4378mod bar {
4379 use super as foo$0;
4380}
4381"#,
4382 expect![[r#"
4383 *foo*
4384
4385 ```rust
4386 extern crate test
4387 ```
4388 "#]],
4389 );
4390 check(
4391 r#"
4392use crate as foo$0;
4393"#,
4394 expect![[r#"
4395 *foo*
4396
4397 ```rust
4398 extern crate test
4399 ```
4400 "#]],
4401 );
4402}
4403
4404#[test]
4405fn hover_attribute_in_macro() {
4406 check(
4407 r#"
4408//- minicore:derive
4409macro_rules! identity {
4410 ($struct:item) => {
4411 $struct
4412 };
4413}
4414#[rustc_builtin_macro]
4415pub macro Copy {}
4416identity!{
4417 #[derive(Copy$0)]
4418 struct Foo;
4419}
4420"#,
4421 expect![[r#"
4422 *Copy*
4423
4424 ```rust
4425 test
4426 ```
4427
4428 ```rust
4429 macro Copy
4430 ```
4431 "#]],
4432 );
4433}
4434
4435#[test]
4436fn hover_derive_input() {
4437 check(
4438 r#"
4439//- minicore:derive
4440#[rustc_builtin_macro]
4441pub macro Copy {}
4442#[derive(Copy$0)]
4443struct Foo;
4444"#,
4445 expect![[r#"
4446 *Copy*
4447
4448 ```rust
4449 test
4450 ```
4451
4452 ```rust
4453 macro Copy
4454 ```
4455 "#]],
4456 );
4457 check(
4458 r#"
4459//- minicore:derive
4460mod foo {
4461 #[rustc_builtin_macro]
4462 pub macro Copy {}
4463}
4464#[derive(foo::Copy$0)]
4465struct Foo;
4466"#,
4467 expect![[r#"
4468 *Copy*
4469
4470 ```rust
4471 test::foo
4472 ```
4473
4474 ```rust
4475 macro Copy
4476 ```
4477 "#]],
4478 );
4479}
4480
4481#[test]
4482fn hover_range_math() {
4483 check_hover_range(
4484 r#"
4485fn f() { let expr = $01 + 2 * 3$0 }
4486"#,
4487 expect![[r#"
4488 ```rust
4489 i32
4490 ```"#]],
4491 );
4492
4493 check_hover_range(
4494 r#"
4495fn f() { let expr = 1 $0+ 2 * $03 }
4496"#,
4497 expect![[r#"
4498 ```rust
4499 i32
4500 ```"#]],
4501 );
4502
4503 check_hover_range(
4504 r#"
4505fn f() { let expr = 1 + $02 * 3$0 }
4506"#,
4507 expect![[r#"
4508 ```rust
4509 i32
4510 ```"#]],
4511 );
4512}
4513
4514#[test]
4515fn hover_range_arrays() {
4516 check_hover_range(
4517 r#"
4518fn f() { let expr = $0[1, 2, 3, 4]$0 }
4519"#,
4520 expect![[r#"
4521 ```rust
4522 [i32; 4]
4523 ```"#]],
4524 );
4525
4526 check_hover_range(
4527 r#"
4528fn f() { let expr = [1, 2, $03, 4]$0 }
4529"#,
4530 expect![[r#"
4531 ```rust
4532 [i32; 4]
4533 ```"#]],
4534 );
4535
4536 check_hover_range(
4537 r#"
4538fn f() { let expr = [1, 2, $03$0, 4] }
4539"#,
4540 expect![[r#"
4541 ```rust
4542 i32
4543 ```"#]],
4544 );
4545}
4546
4547#[test]
4548fn hover_range_functions() {
4549 check_hover_range(
4550 r#"
4551fn f<T>(a: &[T]) { }
4552fn b() { $0f$0(&[1, 2, 3, 4, 5]); }
4553"#,
4554 expect![[r#"
4555 ```rust
4556 fn f<i32>(&[i32])
4557 ```"#]],
4558 );
4559
4560 check_hover_range(
4561 r#"
4562fn f<T>(a: &[T]) { }
4563fn b() { f($0&[1, 2, 3, 4, 5]$0); }
4564"#,
4565 expect![[r#"
4566 ```rust
4567 &[i32; 5]
4568 ```"#]],
4569 );
4570}
4571
4572#[test]
4573fn hover_range_shows_nothing_when_invalid() {
4574 check_hover_range_no_results(
4575 r#"
4576fn f<T>(a: &[T]) { }
4577fn b()$0 { f(&[1, 2, 3, 4, 5]); }$0
4578"#,
4579 );
4580
4581 check_hover_range_no_results(
4582 r#"
4583fn f<T>$0(a: &[T]) { }
4584fn b() { f(&[1, 2, 3,$0 4, 5]); }
4585"#,
4586 );
4587
4588 check_hover_range_no_results(
4589 r#"
4590fn $0f() { let expr = [1, 2, 3, 4]$0 }
4591"#,
4592 );
4593}
4594
4595#[test]
4596fn hover_range_shows_unit_for_statements() {
4597 check_hover_range(
4598 r#"
4599fn f<T>(a: &[T]) { }
4600fn b() { $0f(&[1, 2, 3, 4, 5]); }$0
4601"#,
4602 expect![[r#"
4603 ```rust
4604 ()
4605 ```"#]],
4606 );
4607
4608 check_hover_range(
4609 r#"
4610fn f() { let expr$0 = $0[1, 2, 3, 4] }
4611"#,
4612 expect![[r#"
4613 ```rust
4614 ()
4615 ```"#]],
4616 );
4617}
4618
4619#[test]
4620fn hover_range_for_pat() {
4621 check_hover_range(
4622 r#"
4623fn foo() {
4624 let $0x$0 = 0;
4625}
4626"#,
4627 expect![[r#"
4628 ```rust
4629 i32
4630 ```"#]],
4631 );
4632
4633 check_hover_range(
4634 r#"
4635fn foo() {
4636 let $0x$0 = "";
4637}
4638"#,
4639 expect![[r#"
4640 ```rust
4641 &str
4642 ```"#]],
4643 );
4644}
4645
4646#[test]
4647fn hover_range_shows_coercions_if_applicable_expr() {
4648 check_hover_range(
4649 r#"
4650fn foo() {
4651 let x: &u32 = $0&&&&&0$0;
4652}
4653"#,
4654 expect![[r#"
4655 ```text
4656 Type: &&&&&u32
4657 Coerced to: &u32
4658 ```
4659 "#]],
4660 );
4661 check_hover_range(
4662 r#"
4663fn foo() {
4664 let x: *const u32 = $0&0$0;
4665}
4666"#,
4667 expect![[r#"
4668 ```text
4669 Type: &u32
4670 Coerced to: *const u32
4671 ```
4672 "#]],
4673 );
4674}
4675
4676#[test]
4677fn hover_range_shows_type_actions() {
4678 check_actions(
4679 r#"
4680struct Foo;
4681fn foo() {
4682 let x: &Foo = $0&&&&&Foo$0;
4683}
4684"#,
4685 expect![[r#"
4686 [
4687 GoToType(
4688 [
4689 HoverGotoTypeData {
4690 mod_path: "test::Foo",
4691 nav: NavigationTarget {
4692 file_id: FileId(
4693 0,
4694 ),
4695 full_range: 0..11,
4696 focus_range: 7..10,
4697 name: "Foo",
4698 kind: Struct,
4699 description: "struct Foo",
4700 },
4701 },
4702 ],
4703 ),
4704 ]
4705 "#]],
4706 );
4707}
4708
4709#[test]
4710fn hover_try_expr_res() {
4711 check_hover_range(
4712 r#"
4713//- minicore:result
4714struct FooError;
4715
4716fn foo() -> Result<(), FooError> {
4717 Ok($0Result::<(), FooError>::Ok(())?$0)
4718}
4719"#,
4720 expect![[r#"
4721 ```rust
4722 ()
4723 ```"#]],
4724 );
4725 check_hover_range(
4726 r#"
4727//- minicore:result
4728struct FooError;
4729struct BarError;
4730
4731fn foo() -> Result<(), FooError> {
4732 Ok($0Result::<(), BarError>::Ok(())?$0)
4733}
4734"#,
4735 expect![[r#"
4736 ```text
4737 Try Error Type: BarError
4738 Propagated as: FooError
4739 ```
4740 "#]],
4741 );
4742}
4743
4744#[test]
4745fn hover_try_expr() {
4746 check_hover_range(
4747 r#"
4748struct NotResult<T, U>(T, U);
4749struct Short;
4750struct Looooong;
4751
4752fn foo() -> NotResult<(), Looooong> {
4753 $0NotResult((), Short)?$0;
4754}
4755"#,
4756 expect![[r#"
4757 ```text
4758 Try Target Type: NotResult<(), Short>
4759 Propagated as: NotResult<(), Looooong>
4760 ```
4761 "#]],
4762 );
4763 check_hover_range(
4764 r#"
4765struct NotResult<T, U>(T, U);
4766struct Short;
4767struct Looooong;
4768
4769fn foo() -> NotResult<(), Short> {
4770 $0NotResult((), Looooong)?$0;
4771}
4772"#,
4773 expect![[r#"
4774 ```text
4775 Try Target Type: NotResult<(), Looooong>
4776 Propagated as: NotResult<(), Short>
4777 ```
4778 "#]],
4779 );
4780}
4781
4782#[test]
4783fn hover_try_expr_option() {
4784 cov_mark::check!(hover_try_expr_opt_opt);
4785 check_hover_range(
4786 r#"
4787//- minicore: option, try
4788
4789fn foo() -> Option<()> {
4790 $0Some(0)?$0;
4791 None
4792}
4793"#,
4794 expect![[r#"
4795 ```rust
4796 <Option<i32> as Try>::Output
4797 ```"#]],
4798 );
4799}
4800
4801#[test]
4802fn hover_deref_expr() {
4803 check_hover_range(
4804 r#"
4805//- minicore: deref
4806use core::ops::Deref;
4807
4808struct DerefExample<T> {
4809 value: T
4810}
4811
4812impl<T> Deref for DerefExample<T> {
4813 type Target = T;
4814
4815 fn deref(&self) -> &Self::Target {
4816 &self.value
4817 }
4818}
4819
4820fn foo() {
4821 let x = DerefExample { value: 0 };
4822 let y: i32 = $0*x$0;
4823}
4824"#,
4825 expect![[r#"
4826 ```text
4827 Dereferenced from: DerefExample<i32>
4828 To type: i32
4829 ```
4830 "#]],
4831 );
4832}
4833
4834#[test]
4835fn hover_deref_expr_with_coercion() {
4836 check_hover_range(
4837 r#"
4838//- minicore: deref
4839use core::ops::Deref;
4840
4841struct DerefExample<T> {
4842 value: T
4843}
4844
4845impl<T> Deref for DerefExample<T> {
4846 type Target = T;
4847
4848 fn deref(&self) -> &Self::Target {
4849 &self.value
4850 }
4851}
4852
4853fn foo() {
4854 let x = DerefExample { value: &&&&&0 };
4855 let y: &i32 = $0*x$0;
4856}
4857"#,
4858 expect![[r#"
4859 ```text
4860 Dereferenced from: DerefExample<&&&&&i32>
4861 To type: &&&&&i32
4862 Coerced to: &i32
4863 ```
4864 "#]],
4865 );
4866}
4867
4868#[test]
4869fn hover_intra_in_macro() {
4870 check(
4871 r#"
4872macro_rules! foo_macro {
4873 ($(#[$attr:meta])* $name:ident) => {
4874 $(#[$attr])*
4875 pub struct $name;
4876 }
4877}
4878
4879foo_macro!(
4880 /// Doc comment for [`Foo$0`]
4881 Foo
4882);
4883"#,
4884 expect![[r#"
4885 *[`Foo`]*
4886
4887 ```rust
4888 test
4889 ```
4890
4891 ```rust
4892 pub struct Foo
4893 ```
4894
4895 ---
4896
4897 Doc comment for [`Foo`](https://docs.rs/test/*/test/struct.Foo.html)
4898 "#]],
4899 );
4900}
4901
4902#[test]
4903fn hover_intra_in_attr() {
4904 check(
4905 r#"
4906#[doc = "Doc comment for [`Foo$0`]"]
4907pub struct Foo;
4908"#,
4909 expect![[r#"
4910 *[`Foo`]*
4911
4912 ```rust
4913 test
4914 ```
4915
4916 ```rust
4917 pub struct Foo
4918 ```
4919
4920 ---
4921
4922 Doc comment for [`Foo`](https://docs.rs/test/*/test/struct.Foo.html)
4923 "#]],
4924 );
4925}
4926
4927#[test]
4928fn hover_inert_attr() {
4929 check(
4930 r#"
4931#[doc$0 = ""]
4932pub struct Foo;
4933"#,
4934 expect![[r##"
4935 *doc*
4936
4937 ```rust
4938 #[doc]
4939 ```
4940
4941 ---
4942
4943 Valid forms are:
4944
4945 * \#\[doc(hidden|inline|...)\]
4946 * \#\[doc = string\]
4947 "##]],
4948 );
4949 check(
4950 r#"
4951#[allow$0()]
4952pub struct Foo;
4953"#,
4954 expect![[r##"
4955 *allow*
4956
4957 ```rust
4958 #[allow]
4959 ```
4960
4961 ---
4962
4963 Valid forms are:
4964
4965 * \#\[allow(lint1, lint2, ..., /\*opt\*/ reason = "...")\]
4966 "##]],
4967 );
4968}
4969
4970#[test]
4971fn hover_dollar_crate() {
4972 // $crate should be resolved to the right crate name.
4973
4974 check(
4975 r#"
4976//- /main.rs crate:main deps:dep
4977dep::m!(KONST$0);
4978//- /dep.rs crate:dep
4979#[macro_export]
4980macro_rules! m {
4981 ( $name:ident ) => { const $name: $crate::Type = $crate::Type; };
4982}
4983
4984pub struct Type;
4985"#,
4986 expect![[r#"
4987 *KONST*
4988
4989 ```rust
4990 main
4991 ```
4992
4993 ```rust
4994 const KONST: dep::Type = $crate::Type
4995 ```
4996 "#]],
4997 );
4998}
4999
5000#[test]
5001fn hover_record_variant() {
5002 check(
5003 r#"
5004enum Enum {
5005 RecordV$0 { field: u32 }
5006}
5007"#,
5008 expect![[r#"
5009 *RecordV*
5010
5011 ```rust
5012 test::Enum
5013 ```
5014
5015 ```rust
5016 RecordV { field: u32 }
5017 ```
5018 "#]],
5019 );
5020}
5021
5022#[test]
5023fn hover_trait_impl_assoc_item_def_doc_forwarding() {
5024 check(
5025 r#"
5026trait T {
5027 /// Trait docs
5028 fn func() {}
5029}
5030impl T for () {
5031 fn func$0() {}
5032}
5033"#,
5034 expect![[r#"
5035 *func*
5036
5037 ```rust
5038 test
5039 ```
5040
5041 ```rust
5042 fn func()
5043 ```
5044
5045 ---
5046
5047 Trait docs
5048 "#]],
5049 );
5050}
5051
5052#[test]
5053fn hover_ranged_macro_call() {
5054 check_hover_range(
5055 r#"
5056macro_rules! __rust_force_expr {
5057 ($e:expr) => {
5058 $e
5059 };
5060}
5061macro_rules! vec {
5062 ($elem:expr) => {
5063 __rust_force_expr!($elem)
5064 };
5065}
5066
5067struct Struct;
5068impl Struct {
5069 fn foo(self) {}
5070}
5071
5072fn f() {
5073 $0vec![Struct]$0;
5074}
5075"#,
5076 expect![[r#"
5077 ```rust
5078 Struct
5079 ```"#]],
5080 );
5081}
f2b60f7d
FG
5082
5083#[test]
5084fn hover_deref() {
5085 check(
5086 r#"
5087//- minicore: deref
5088
5089struct Struct(usize);
5090
5091impl core::ops::Deref for Struct {
5092 type Target = usize;
5093
5094 fn deref(&self) -> &Self::Target {
5095 &self.0
5096 }
5097}
5098
5099fn f() {
5100 $0*Struct(0);
5101}
5102"#,
5103 expect![[r#"
5104 ***
5105
5106 ```rust
5107 test::Struct
5108 ```
5109
5110 ```rust
5111 fn deref(&self) -> &Self::Target
5112 ```
5113 "#]],
5114 );
5115}
5116
5117#[test]
5118fn static_const_macro_expanded_body() {
5119 check(
5120 r#"
5121macro_rules! m {
5122 () => {
5123 pub const V: i8 = {
5124 let e = 123;
5125 f(e) // Prevent const eval from evaluating this constant, we want to print the body's code.
5126 };
5127 };
5128}
5129m!();
5130fn main() { $0V; }
5131"#,
5132 expect![[r#"
5133 *V*
5134
5135 ```rust
5136 test
5137 ```
5138
5139 ```rust
5140 pub const V: i8 = {
5141 let e = 123;
5142 f(e)
5143 }
5144 ```
5145 "#]],
5146 );
5147 check(
5148 r#"
5149macro_rules! m {
5150 () => {
5151 pub static V: i8 = {
5152 let e = 123;
5153 };
5154 };
5155}
5156m!();
5157fn main() { $0V; }
5158"#,
5159 expect![[r#"
5160 *V*
5161
5162 ```rust
5163 test
5164 ```
5165
5166 ```rust
5167 pub static V: i8 = {
5168 let e = 123;
5169 }
5170 ```
5171 "#]],
5172 );
5173}