]> git.proxmox.com Git - rustc.git/blob - src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / ide / src / goto_definition.rs
1 use std::mem::discriminant;
2
3 use crate::{doc_links::token_as_doc_comment, FilePosition, NavigationTarget, RangeInfo, TryToNav};
4 use hir::{AsAssocItem, AssocItem, Semantics};
5 use ide_db::{
6 base_db::{AnchoredPath, FileId, FileLoader},
7 defs::{Definition, IdentClass},
8 helpers::pick_best_token,
9 RootDatabase,
10 };
11 use itertools::Itertools;
12 use syntax::{ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, T};
13
14 // Feature: Go to Definition
15 //
16 // Navigates to the definition of an identifier.
17 //
18 // For outline modules, this will navigate to the source file of the module.
19 //
20 // |===
21 // | Editor | Shortcut
22 //
23 // | VS Code | kbd:[F12]
24 // |===
25 //
26 // image::https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif[]
27 pub(crate) fn goto_definition(
28 db: &RootDatabase,
29 position: FilePosition,
30 ) -> Option<RangeInfo<Vec<NavigationTarget>>> {
31 let sema = &Semantics::new(db);
32 let file = sema.parse(position.file_id).syntax().clone();
33 let original_token =
34 pick_best_token(file.token_at_offset(position.offset), |kind| match kind {
35 IDENT
36 | INT_NUMBER
37 | LIFETIME_IDENT
38 | T![self]
39 | T![super]
40 | T![crate]
41 | T![Self]
42 | COMMENT => 4,
43 // index and prefix ops
44 T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3,
45 kind if kind.is_keyword() => 2,
46 T!['('] | T![')'] => 2,
47 kind if kind.is_trivia() => 0,
48 _ => 1,
49 })?;
50 if let Some(doc_comment) = token_as_doc_comment(&original_token) {
51 return doc_comment.get_definition_with_descend_at(sema, position.offset, |def, _, _| {
52 let nav = def.try_to_nav(db)?;
53 Some(RangeInfo::new(original_token.text_range(), vec![nav]))
54 });
55 }
56 let navs = sema
57 .descend_into_macros(original_token.clone())
58 .into_iter()
59 .filter_map(|token| {
60 let parent = token.parent()?;
61 if let Some(tt) = ast::TokenTree::cast(parent) {
62 if let Some(x) = try_lookup_include_path(sema, tt, token.clone(), position.file_id)
63 {
64 return Some(vec![x]);
65 }
66 }
67 Some(
68 IdentClass::classify_token(sema, &token)?
69 .definitions()
70 .into_iter()
71 .flat_map(|def| {
72 try_filter_trait_item_definition(sema, &def)
73 .unwrap_or_else(|| def_to_nav(sema.db, def))
74 })
75 .collect(),
76 )
77 })
78 .flatten()
79 .unique()
80 .collect::<Vec<NavigationTarget>>();
81
82 Some(RangeInfo::new(original_token.text_range(), navs))
83 }
84
85 fn try_lookup_include_path(
86 sema: &Semantics<'_, RootDatabase>,
87 tt: ast::TokenTree,
88 token: SyntaxToken,
89 file_id: FileId,
90 ) -> Option<NavigationTarget> {
91 let token = ast::String::cast(token)?;
92 let path = token.value()?.into_owned();
93 let macro_call = tt.syntax().parent().and_then(ast::MacroCall::cast)?;
94 let name = macro_call.path()?.segment()?.name_ref()?;
95 if !matches!(&*name.text(), "include" | "include_str" | "include_bytes") {
96 return None;
97 }
98 let file_id = sema.db.resolve_path(AnchoredPath { anchor: file_id, path: &path })?;
99 let size = sema.db.file_text(file_id).len().try_into().ok()?;
100 Some(NavigationTarget {
101 file_id,
102 full_range: TextRange::new(0.into(), size),
103 name: path.into(),
104 focus_range: None,
105 kind: None,
106 container_name: None,
107 description: None,
108 docs: None,
109 })
110 }
111 /// finds the trait definition of an impl'd item, except function
112 /// e.g.
113 /// ```rust
114 /// trait A { type a; }
115 /// struct S;
116 /// impl A for S { type a = i32; } // <-- on this associate type, will get the location of a in the trait
117 /// ```
118 fn try_filter_trait_item_definition(
119 sema: &Semantics<'_, RootDatabase>,
120 def: &Definition,
121 ) -> Option<Vec<NavigationTarget>> {
122 let db = sema.db;
123 let assoc = def.as_assoc_item(db)?;
124 match assoc {
125 AssocItem::Function(..) => None,
126 AssocItem::Const(..) | AssocItem::TypeAlias(..) => {
127 let imp = match assoc.container(db) {
128 hir::AssocItemContainer::Impl(imp) => imp,
129 _ => return None,
130 };
131 let trait_ = imp.trait_(db)?;
132 let name = def.name(db)?;
133 let discri_value = discriminant(&assoc);
134 trait_
135 .items(db)
136 .iter()
137 .filter(|itm| discriminant(*itm) == discri_value)
138 .find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(db)).flatten())
139 .map(|it| vec![it])
140 }
141 }
142 }
143
144 fn def_to_nav(db: &RootDatabase, def: Definition) -> Vec<NavigationTarget> {
145 def.try_to_nav(db).map(|it| vec![it]).unwrap_or_default()
146 }
147
148 #[cfg(test)]
149 mod tests {
150 use ide_db::base_db::FileRange;
151 use itertools::Itertools;
152
153 use crate::fixture;
154
155 #[track_caller]
156 fn check(ra_fixture: &str) {
157 let (analysis, position, expected) = fixture::annotations(ra_fixture);
158 let navs = analysis.goto_definition(position).unwrap().expect("no definition found").info;
159 if navs.is_empty() {
160 panic!("unresolved reference")
161 }
162
163 let cmp = |&FileRange { file_id, range }: &_| (file_id, range.start());
164 let navs = navs
165 .into_iter()
166 .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() })
167 .sorted_by_key(cmp)
168 .collect::<Vec<_>>();
169 let expected = expected
170 .into_iter()
171 .map(|(FileRange { file_id, range }, _)| FileRange { file_id, range })
172 .sorted_by_key(cmp)
173 .collect::<Vec<_>>();
174 assert_eq!(expected, navs);
175 }
176
177 fn check_unresolved(ra_fixture: &str) {
178 let (analysis, position) = fixture::position(ra_fixture);
179 let navs = analysis.goto_definition(position).unwrap().expect("no definition found").info;
180
181 assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {:?}", navs)
182 }
183
184 #[test]
185 fn goto_def_if_items_same_name() {
186 check(
187 r#"
188 trait Trait {
189 type A;
190 const A: i32;
191 //^
192 }
193
194 struct T;
195 impl Trait for T {
196 type A = i32;
197 const A$0: i32 = -9;
198 }"#,
199 );
200 }
201 #[test]
202 fn goto_def_in_mac_call_in_attr_invoc() {
203 check(
204 r#"
205 //- proc_macros: identity
206 pub struct Struct {
207 // ^^^^^^
208 field: i32,
209 }
210
211 macro_rules! identity {
212 ($($tt:tt)*) => {$($tt)*};
213 }
214
215 #[proc_macros::identity]
216 fn function() {
217 identity!(Struct$0 { field: 0 });
218 }
219
220 "#,
221 )
222 }
223
224 #[test]
225 fn goto_def_for_extern_crate() {
226 check(
227 r#"
228 //- /main.rs crate:main deps:std
229 extern crate std$0;
230 //- /std/lib.rs crate:std
231 // empty
232 //^file
233 "#,
234 )
235 }
236
237 #[test]
238 fn goto_def_for_renamed_extern_crate() {
239 check(
240 r#"
241 //- /main.rs crate:main deps:std
242 extern crate std as abc$0;
243 //- /std/lib.rs crate:std
244 // empty
245 //^file
246 "#,
247 )
248 }
249
250 #[test]
251 fn goto_def_in_items() {
252 check(
253 r#"
254 struct Foo;
255 //^^^
256 enum E { X(Foo$0) }
257 "#,
258 );
259 }
260
261 #[test]
262 fn goto_def_at_start_of_item() {
263 check(
264 r#"
265 struct Foo;
266 //^^^
267 enum E { X($0Foo) }
268 "#,
269 );
270 }
271
272 #[test]
273 fn goto_definition_resolves_correct_name() {
274 check(
275 r#"
276 //- /lib.rs
277 use a::Foo;
278 mod a;
279 mod b;
280 enum E { X(Foo$0) }
281
282 //- /a.rs
283 struct Foo;
284 //^^^
285 //- /b.rs
286 struct Foo;
287 "#,
288 );
289 }
290
291 #[test]
292 fn goto_def_for_module_declaration() {
293 check(
294 r#"
295 //- /lib.rs
296 mod $0foo;
297
298 //- /foo.rs
299 // empty
300 //^file
301 "#,
302 );
303
304 check(
305 r#"
306 //- /lib.rs
307 mod $0foo;
308
309 //- /foo/mod.rs
310 // empty
311 //^file
312 "#,
313 );
314 }
315
316 #[test]
317 fn goto_def_for_macros() {
318 check(
319 r#"
320 macro_rules! foo { () => { () } }
321 //^^^
322 fn bar() {
323 $0foo!();
324 }
325 "#,
326 );
327 }
328
329 #[test]
330 fn goto_def_for_macros_from_other_crates() {
331 check(
332 r#"
333 //- /lib.rs crate:main deps:foo
334 use foo::foo;
335 fn bar() {
336 $0foo!();
337 }
338
339 //- /foo/lib.rs crate:foo
340 #[macro_export]
341 macro_rules! foo { () => { () } }
342 //^^^
343 "#,
344 );
345 }
346
347 #[test]
348 fn goto_def_for_macros_in_use_tree() {
349 check(
350 r#"
351 //- /lib.rs crate:main deps:foo
352 use foo::foo$0;
353
354 //- /foo/lib.rs crate:foo
355 #[macro_export]
356 macro_rules! foo { () => { () } }
357 //^^^
358 "#,
359 );
360 }
361
362 #[test]
363 fn goto_def_for_macro_defined_fn_with_arg() {
364 check(
365 r#"
366 //- /lib.rs
367 macro_rules! define_fn {
368 ($name:ident) => (fn $name() {})
369 }
370
371 define_fn!(foo);
372 //^^^
373
374 fn bar() {
375 $0foo();
376 }
377 "#,
378 );
379 }
380
381 #[test]
382 fn goto_def_for_macro_defined_fn_no_arg() {
383 check(
384 r#"
385 //- /lib.rs
386 macro_rules! define_fn {
387 () => (fn foo() {})
388 }
389
390 define_fn!();
391 //^^^^^^^^^^^^^
392
393 fn bar() {
394 $0foo();
395 }
396 "#,
397 );
398 }
399
400 #[test]
401 fn goto_definition_works_for_macro_inside_pattern() {
402 check(
403 r#"
404 //- /lib.rs
405 macro_rules! foo {() => {0}}
406 //^^^
407
408 fn bar() {
409 match (0,1) {
410 ($0foo!(), _) => {}
411 }
412 }
413 "#,
414 );
415 }
416
417 #[test]
418 fn goto_definition_works_for_macro_inside_match_arm_lhs() {
419 check(
420 r#"
421 //- /lib.rs
422 macro_rules! foo {() => {0}}
423 //^^^
424 fn bar() {
425 match 0 {
426 $0foo!() => {}
427 }
428 }
429 "#,
430 );
431 }
432
433 #[test]
434 fn goto_def_for_use_alias() {
435 check(
436 r#"
437 //- /lib.rs crate:main deps:foo
438 use foo as bar$0;
439
440 //- /foo/lib.rs crate:foo
441 // empty
442 //^file
443 "#,
444 );
445 }
446
447 #[test]
448 fn goto_def_for_use_alias_foo_macro() {
449 check(
450 r#"
451 //- /lib.rs crate:main deps:foo
452 use foo::foo as bar$0;
453
454 //- /foo/lib.rs crate:foo
455 #[macro_export]
456 macro_rules! foo { () => { () } }
457 //^^^
458 "#,
459 );
460 }
461
462 #[test]
463 fn goto_def_for_methods() {
464 check(
465 r#"
466 struct Foo;
467 impl Foo {
468 fn frobnicate(&self) { }
469 //^^^^^^^^^^
470 }
471
472 fn bar(foo: &Foo) {
473 foo.frobnicate$0();
474 }
475 "#,
476 );
477 }
478
479 #[test]
480 fn goto_def_for_fields() {
481 check(
482 r#"
483 struct Foo {
484 spam: u32,
485 } //^^^^
486
487 fn bar(foo: &Foo) {
488 foo.spam$0;
489 }
490 "#,
491 );
492 }
493
494 #[test]
495 fn goto_def_for_record_fields() {
496 check(
497 r#"
498 //- /lib.rs
499 struct Foo {
500 spam: u32,
501 } //^^^^
502
503 fn bar() -> Foo {
504 Foo {
505 spam$0: 0,
506 }
507 }
508 "#,
509 );
510 }
511
512 #[test]
513 fn goto_def_for_record_pat_fields() {
514 check(
515 r#"
516 //- /lib.rs
517 struct Foo {
518 spam: u32,
519 } //^^^^
520
521 fn bar(foo: Foo) -> Foo {
522 let Foo { spam$0: _, } = foo
523 }
524 "#,
525 );
526 }
527
528 #[test]
529 fn goto_def_for_record_fields_macros() {
530 check(
531 r"
532 macro_rules! m { () => { 92 };}
533 struct Foo { spam: u32 }
534 //^^^^
535
536 fn bar() -> Foo {
537 Foo { spam$0: m!() }
538 }
539 ",
540 );
541 }
542
543 #[test]
544 fn goto_for_tuple_fields() {
545 check(
546 r#"
547 struct Foo(u32);
548 //^^^
549
550 fn bar() {
551 let foo = Foo(0);
552 foo.$00;
553 }
554 "#,
555 );
556 }
557
558 #[test]
559 fn goto_def_for_ufcs_inherent_methods() {
560 check(
561 r#"
562 struct Foo;
563 impl Foo {
564 fn frobnicate() { }
565 } //^^^^^^^^^^
566
567 fn bar(foo: &Foo) {
568 Foo::frobnicate$0();
569 }
570 "#,
571 );
572 }
573
574 #[test]
575 fn goto_def_for_ufcs_trait_methods_through_traits() {
576 check(
577 r#"
578 trait Foo {
579 fn frobnicate();
580 } //^^^^^^^^^^
581
582 fn bar() {
583 Foo::frobnicate$0();
584 }
585 "#,
586 );
587 }
588
589 #[test]
590 fn goto_def_for_ufcs_trait_methods_through_self() {
591 check(
592 r#"
593 struct Foo;
594 trait Trait {
595 fn frobnicate();
596 } //^^^^^^^^^^
597 impl Trait for Foo {}
598
599 fn bar() {
600 Foo::frobnicate$0();
601 }
602 "#,
603 );
604 }
605
606 #[test]
607 fn goto_definition_on_self() {
608 check(
609 r#"
610 struct Foo;
611 impl Foo {
612 //^^^
613 pub fn new() -> Self {
614 Self$0 {}
615 }
616 }
617 "#,
618 );
619 check(
620 r#"
621 struct Foo;
622 impl Foo {
623 //^^^
624 pub fn new() -> Self$0 {
625 Self {}
626 }
627 }
628 "#,
629 );
630
631 check(
632 r#"
633 enum Foo { A }
634 impl Foo {
635 //^^^
636 pub fn new() -> Self$0 {
637 Foo::A
638 }
639 }
640 "#,
641 );
642
643 check(
644 r#"
645 enum Foo { A }
646 impl Foo {
647 //^^^
648 pub fn thing(a: &Self$0) {
649 }
650 }
651 "#,
652 );
653 }
654
655 #[test]
656 fn goto_definition_on_self_in_trait_impl() {
657 check(
658 r#"
659 struct Foo;
660 trait Make {
661 fn new() -> Self;
662 }
663 impl Make for Foo {
664 //^^^
665 fn new() -> Self {
666 Self$0 {}
667 }
668 }
669 "#,
670 );
671
672 check(
673 r#"
674 struct Foo;
675 trait Make {
676 fn new() -> Self;
677 }
678 impl Make for Foo {
679 //^^^
680 fn new() -> Self$0 {
681 Self {}
682 }
683 }
684 "#,
685 );
686 }
687
688 #[test]
689 fn goto_def_when_used_on_definition_name_itself() {
690 check(
691 r#"
692 struct Foo$0 { value: u32 }
693 //^^^
694 "#,
695 );
696
697 check(
698 r#"
699 struct Foo {
700 field$0: string,
701 } //^^^^^
702 "#,
703 );
704
705 check(
706 r#"
707 fn foo_test$0() { }
708 //^^^^^^^^
709 "#,
710 );
711
712 check(
713 r#"
714 enum Foo$0 { Variant }
715 //^^^
716 "#,
717 );
718
719 check(
720 r#"
721 enum Foo {
722 Variant1,
723 Variant2$0,
724 //^^^^^^^^
725 Variant3,
726 }
727 "#,
728 );
729
730 check(
731 r#"
732 static INNER$0: &str = "";
733 //^^^^^
734 "#,
735 );
736
737 check(
738 r#"
739 const INNER$0: &str = "";
740 //^^^^^
741 "#,
742 );
743
744 check(
745 r#"
746 type Thing$0 = Option<()>;
747 //^^^^^
748 "#,
749 );
750
751 check(
752 r#"
753 trait Foo$0 { }
754 //^^^
755 "#,
756 );
757
758 check(
759 r#"
760 mod bar$0 { }
761 //^^^
762 "#,
763 );
764 }
765
766 #[test]
767 fn goto_from_macro() {
768 check(
769 r#"
770 macro_rules! id {
771 ($($tt:tt)*) => { $($tt)* }
772 }
773 fn foo() {}
774 //^^^
775 id! {
776 fn bar() {
777 fo$0o();
778 }
779 }
780 mod confuse_index { fn foo(); }
781 "#,
782 );
783 }
784
785 #[test]
786 fn goto_through_format() {
787 check(
788 r#"
789 #[macro_export]
790 macro_rules! format {
791 ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*)))
792 }
793 #[rustc_builtin_macro]
794 #[macro_export]
795 macro_rules! format_args {
796 ($fmt:expr) => ({ /* compiler built-in */ });
797 ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
798 }
799 pub mod __export {
800 pub use crate::format_args;
801 fn foo() {} // for index confusion
802 }
803 fn foo() -> i8 {}
804 //^^^
805 fn test() {
806 format!("{}", fo$0o())
807 }
808 "#,
809 );
810 }
811
812 #[test]
813 fn goto_through_included_file() {
814 check(
815 r#"
816 //- /main.rs
817 #[rustc_builtin_macro]
818 macro_rules! include {}
819
820 include!("foo.rs");
821 //^^^^^^^^^^^^^^^^^^^
822
823 fn f() {
824 foo$0();
825 }
826
827 mod confuse_index {
828 pub fn foo() {}
829 }
830
831 //- /foo.rs
832 fn foo() {}
833 "#,
834 );
835 }
836
837 #[test]
838 fn goto_for_type_param() {
839 check(
840 r#"
841 struct Foo<T: Clone> { t: $0T }
842 //^
843 "#,
844 );
845 }
846
847 #[test]
848 fn goto_within_macro() {
849 check(
850 r#"
851 macro_rules! id {
852 ($($tt:tt)*) => ($($tt)*)
853 }
854
855 fn foo() {
856 let x = 1;
857 //^
858 id!({
859 let y = $0x;
860 let z = y;
861 });
862 }
863 "#,
864 );
865
866 check(
867 r#"
868 macro_rules! id {
869 ($($tt:tt)*) => ($($tt)*)
870 }
871
872 fn foo() {
873 let x = 1;
874 id!({
875 let y = x;
876 //^
877 let z = $0y;
878 });
879 }
880 "#,
881 );
882 }
883
884 #[test]
885 fn goto_def_in_local_fn() {
886 check(
887 r#"
888 fn main() {
889 fn foo() {
890 let x = 92;
891 //^
892 $0x;
893 }
894 }
895 "#,
896 );
897 }
898
899 #[test]
900 fn goto_def_in_local_macro() {
901 check(
902 r#"
903 fn bar() {
904 macro_rules! foo { () => { () } }
905 //^^^
906 $0foo!();
907 }
908 "#,
909 );
910 }
911
912 #[test]
913 fn goto_def_for_field_init_shorthand() {
914 check(
915 r#"
916 struct Foo { x: i32 }
917 //^
918 fn main() {
919 let x = 92;
920 //^
921 Foo { x$0 };
922 }
923 "#,
924 )
925 }
926
927 #[test]
928 fn goto_def_for_enum_variant_field() {
929 check(
930 r#"
931 enum Foo {
932 Bar { x: i32 }
933 //^
934 }
935 fn baz(foo: Foo) {
936 match foo {
937 Foo::Bar { x$0 } => x
938 //^
939 };
940 }
941 "#,
942 );
943 }
944
945 #[test]
946 fn goto_def_for_enum_variant_self_pattern_const() {
947 check(
948 r#"
949 enum Foo { Bar }
950 //^^^
951 impl Foo {
952 fn baz(self) {
953 match self { Self::Bar$0 => {} }
954 }
955 }
956 "#,
957 );
958 }
959
960 #[test]
961 fn goto_def_for_enum_variant_self_pattern_record() {
962 check(
963 r#"
964 enum Foo { Bar { val: i32 } }
965 //^^^
966 impl Foo {
967 fn baz(self) -> i32 {
968 match self { Self::Bar$0 { val } => {} }
969 }
970 }
971 "#,
972 );
973 }
974
975 #[test]
976 fn goto_def_for_enum_variant_self_expr_const() {
977 check(
978 r#"
979 enum Foo { Bar }
980 //^^^
981 impl Foo {
982 fn baz(self) { Self::Bar$0; }
983 }
984 "#,
985 );
986 }
987
988 #[test]
989 fn goto_def_for_enum_variant_self_expr_record() {
990 check(
991 r#"
992 enum Foo { Bar { val: i32 } }
993 //^^^
994 impl Foo {
995 fn baz(self) { Self::Bar$0 {val: 4}; }
996 }
997 "#,
998 );
999 }
1000
1001 #[test]
1002 fn goto_def_for_type_alias_generic_parameter() {
1003 check(
1004 r#"
1005 type Alias<T> = T$0;
1006 //^
1007 "#,
1008 )
1009 }
1010
1011 #[test]
1012 fn goto_def_for_macro_container() {
1013 check(
1014 r#"
1015 //- /lib.rs crate:main deps:foo
1016 foo::module$0::mac!();
1017
1018 //- /foo/lib.rs crate:foo
1019 pub mod module {
1020 //^^^^^^
1021 #[macro_export]
1022 macro_rules! _mac { () => { () } }
1023 pub use crate::_mac as mac;
1024 }
1025 "#,
1026 );
1027 }
1028
1029 #[test]
1030 fn goto_def_for_assoc_ty_in_path() {
1031 check(
1032 r#"
1033 trait Iterator {
1034 type Item;
1035 //^^^^
1036 }
1037
1038 fn f() -> impl Iterator<Item$0 = u8> {}
1039 "#,
1040 );
1041 }
1042
1043 #[test]
1044 fn goto_def_for_super_assoc_ty_in_path() {
1045 check(
1046 r#"
1047 trait Super {
1048 type Item;
1049 //^^^^
1050 }
1051
1052 trait Sub: Super {}
1053
1054 fn f() -> impl Sub<Item$0 = u8> {}
1055 "#,
1056 );
1057 }
1058
1059 #[test]
1060 fn unknown_assoc_ty() {
1061 check_unresolved(
1062 r#"
1063 trait Iterator { type Item; }
1064 fn f() -> impl Iterator<Invalid$0 = u8> {}
1065 "#,
1066 )
1067 }
1068
1069 #[test]
1070 fn goto_def_for_assoc_ty_in_path_multiple() {
1071 check(
1072 r#"
1073 trait Iterator {
1074 type A;
1075 //^
1076 type B;
1077 }
1078
1079 fn f() -> impl Iterator<A$0 = u8, B = ()> {}
1080 "#,
1081 );
1082 check(
1083 r#"
1084 trait Iterator {
1085 type A;
1086 type B;
1087 //^
1088 }
1089
1090 fn f() -> impl Iterator<A = u8, B$0 = ()> {}
1091 "#,
1092 );
1093 }
1094
1095 #[test]
1096 fn goto_def_for_assoc_ty_ufcs() {
1097 check(
1098 r#"
1099 trait Iterator {
1100 type Item;
1101 //^^^^
1102 }
1103
1104 fn g() -> <() as Iterator<Item$0 = ()>>::Item {}
1105 "#,
1106 );
1107 }
1108
1109 #[test]
1110 fn goto_def_for_assoc_ty_ufcs_multiple() {
1111 check(
1112 r#"
1113 trait Iterator {
1114 type A;
1115 //^
1116 type B;
1117 }
1118
1119 fn g() -> <() as Iterator<A$0 = (), B = u8>>::B {}
1120 "#,
1121 );
1122 check(
1123 r#"
1124 trait Iterator {
1125 type A;
1126 type B;
1127 //^
1128 }
1129
1130 fn g() -> <() as Iterator<A = (), B$0 = u8>>::A {}
1131 "#,
1132 );
1133 }
1134
1135 #[test]
1136 fn goto_self_param_ty_specified() {
1137 check(
1138 r#"
1139 struct Foo {}
1140
1141 impl Foo {
1142 fn bar(self: &Foo) {
1143 //^^^^
1144 let foo = sel$0f;
1145 }
1146 }"#,
1147 )
1148 }
1149
1150 #[test]
1151 fn goto_self_param_on_decl() {
1152 check(
1153 r#"
1154 struct Foo {}
1155
1156 impl Foo {
1157 fn bar(&self$0) {
1158 //^^^^
1159 }
1160 }"#,
1161 )
1162 }
1163
1164 #[test]
1165 fn goto_lifetime_param_on_decl() {
1166 check(
1167 r#"
1168 fn foo<'foobar$0>(_: &'foobar ()) {
1169 //^^^^^^^
1170 }"#,
1171 )
1172 }
1173
1174 #[test]
1175 fn goto_lifetime_param_decl() {
1176 check(
1177 r#"
1178 fn foo<'foobar>(_: &'foobar$0 ()) {
1179 //^^^^^^^
1180 }"#,
1181 )
1182 }
1183
1184 #[test]
1185 fn goto_lifetime_param_decl_nested() {
1186 check(
1187 r#"
1188 fn foo<'foobar>(_: &'foobar ()) {
1189 fn foo<'foobar>(_: &'foobar$0 ()) {}
1190 //^^^^^^^
1191 }"#,
1192 )
1193 }
1194
1195 #[test]
1196 fn goto_lifetime_hrtb() {
1197 // FIXME: requires the HIR to somehow track these hrtb lifetimes
1198 check_unresolved(
1199 r#"
1200 trait Foo<T> {}
1201 fn foo<T>() where for<'a> T: Foo<&'a$0 (u8, u16)>, {}
1202 //^^
1203 "#,
1204 );
1205 check_unresolved(
1206 r#"
1207 trait Foo<T> {}
1208 fn foo<T>() where for<'a$0> T: Foo<&'a (u8, u16)>, {}
1209 //^^
1210 "#,
1211 );
1212 }
1213
1214 #[test]
1215 fn goto_lifetime_hrtb_for_type() {
1216 // FIXME: requires ForTypes to be implemented
1217 check_unresolved(
1218 r#"trait Foo<T> {}
1219 fn foo<T>() where T: for<'a> Foo<&'a$0 (u8, u16)>, {}
1220 //^^
1221 "#,
1222 );
1223 }
1224
1225 #[test]
1226 fn goto_label() {
1227 check(
1228 r#"
1229 fn foo<'foo>(_: &'foo ()) {
1230 'foo: {
1231 //^^^^
1232 'bar: loop {
1233 break 'foo$0;
1234 }
1235 }
1236 }"#,
1237 )
1238 }
1239
1240 #[test]
1241 fn goto_def_for_intra_doc_link_same_file() {
1242 check(
1243 r#"
1244 /// Blah, [`bar`](bar) .. [`foo`](foo$0) has [`bar`](bar)
1245 pub fn bar() { }
1246
1247 /// You might want to see [`std::fs::read()`] too.
1248 pub fn foo() { }
1249 //^^^
1250
1251 }"#,
1252 )
1253 }
1254
1255 #[test]
1256 fn goto_def_for_intra_doc_link_inner() {
1257 check(
1258 r#"
1259 //- /main.rs
1260 mod m;
1261 struct S;
1262 //^
1263
1264 //- /m.rs
1265 //! [`super::S$0`]
1266 "#,
1267 )
1268 }
1269
1270 #[test]
1271 fn goto_incomplete_field() {
1272 check(
1273 r#"
1274 struct A { a: u32 }
1275 //^
1276 fn foo() { A { a$0: }; }
1277 "#,
1278 )
1279 }
1280
1281 #[test]
1282 fn goto_proc_macro() {
1283 check(
1284 r#"
1285 //- /main.rs crate:main deps:mac
1286 use mac::fn_macro;
1287
1288 fn_macro$0!();
1289
1290 //- /mac.rs crate:mac
1291 #![crate_type="proc-macro"]
1292 #[proc_macro]
1293 fn fn_macro() {}
1294 //^^^^^^^^
1295 "#,
1296 )
1297 }
1298
1299 #[test]
1300 fn goto_intra_doc_links() {
1301 check(
1302 r#"
1303
1304 pub mod theitem {
1305 /// This is the item. Cool!
1306 pub struct TheItem;
1307 //^^^^^^^
1308 }
1309
1310 /// Gives you a [`TheItem$0`].
1311 ///
1312 /// [`TheItem`]: theitem::TheItem
1313 pub fn gimme() -> theitem::TheItem {
1314 theitem::TheItem
1315 }
1316 "#,
1317 );
1318 }
1319
1320 #[test]
1321 fn goto_ident_from_pat_macro() {
1322 check(
1323 r#"
1324 macro_rules! pat {
1325 ($name:ident) => { Enum::Variant1($name) }
1326 }
1327
1328 enum Enum {
1329 Variant1(u8),
1330 Variant2,
1331 }
1332
1333 fn f(e: Enum) {
1334 match e {
1335 pat!(bind) => {
1336 //^^^^
1337 bind$0
1338 }
1339 Enum::Variant2 => {}
1340 }
1341 }
1342 "#,
1343 );
1344 }
1345
1346 #[test]
1347 fn goto_include() {
1348 check(
1349 r#"
1350 //- /main.rs
1351 fn main() {
1352 let str = include_str!("foo.txt$0");
1353 }
1354 //- /foo.txt
1355 // empty
1356 //^file
1357 "#,
1358 );
1359 }
1360 #[cfg(test)]
1361 mod goto_impl_of_trait_fn {
1362 use super::check;
1363 #[test]
1364 fn cursor_on_impl() {
1365 check(
1366 r#"
1367 trait Twait {
1368 fn a();
1369 }
1370
1371 struct Stwuct;
1372
1373 impl Twait for Stwuct {
1374 fn a$0();
1375 //^
1376 }
1377 "#,
1378 );
1379 }
1380 #[test]
1381 fn method_call() {
1382 check(
1383 r#"
1384 trait Twait {
1385 fn a(&self);
1386 }
1387
1388 struct Stwuct;
1389
1390 impl Twait for Stwuct {
1391 fn a(&self){};
1392 //^
1393 }
1394 fn f() {
1395 let s = Stwuct;
1396 s.a$0();
1397 }
1398 "#,
1399 );
1400 }
1401 #[test]
1402 fn path_call() {
1403 check(
1404 r#"
1405 trait Twait {
1406 fn a(&self);
1407 }
1408
1409 struct Stwuct;
1410
1411 impl Twait for Stwuct {
1412 fn a(&self){};
1413 //^
1414 }
1415 fn f() {
1416 let s = Stwuct;
1417 Stwuct::a$0(&s);
1418 }
1419 "#,
1420 );
1421 }
1422 #[test]
1423 fn where_clause_can_work() {
1424 check(
1425 r#"
1426 trait G {
1427 fn g(&self);
1428 }
1429 trait Bound{}
1430 trait EA{}
1431 struct Gen<T>(T);
1432 impl <T:EA> G for Gen<T> {
1433 fn g(&self) {
1434 }
1435 }
1436 impl <T> G for Gen<T>
1437 where T : Bound
1438 {
1439 fn g(&self){
1440 //^
1441 }
1442 }
1443 struct A;
1444 impl Bound for A{}
1445 fn f() {
1446 let gen = Gen::<A>(A);
1447 gen.g$0();
1448 }
1449 "#,
1450 );
1451 }
1452 #[test]
1453 fn wc_case_is_ok() {
1454 check(
1455 r#"
1456 trait G {
1457 fn g(&self);
1458 }
1459 trait BParent{}
1460 trait Bound: BParent{}
1461 struct Gen<T>(T);
1462 impl <T> G for Gen<T>
1463 where T : Bound
1464 {
1465 fn g(&self){
1466 //^
1467 }
1468 }
1469 struct A;
1470 impl Bound for A{}
1471 fn f() {
1472 let gen = Gen::<A>(A);
1473 gen.g$0();
1474 }
1475 "#,
1476 );
1477 }
1478
1479 #[test]
1480 fn method_call_defaulted() {
1481 check(
1482 r#"
1483 trait Twait {
1484 fn a(&self) {}
1485 //^
1486 }
1487
1488 struct Stwuct;
1489
1490 impl Twait for Stwuct {
1491 }
1492 fn f() {
1493 let s = Stwuct;
1494 s.a$0();
1495 }
1496 "#,
1497 );
1498 }
1499
1500 #[test]
1501 fn method_call_on_generic() {
1502 check(
1503 r#"
1504 trait Twait {
1505 fn a(&self) {}
1506 //^
1507 }
1508
1509 fn f<T: Twait>(s: T) {
1510 s.a$0();
1511 }
1512 "#,
1513 );
1514 }
1515 }
1516
1517 #[test]
1518 fn goto_def_of_trait_impl_const() {
1519 check(
1520 r#"
1521 trait Twait {
1522 const NOMS: bool;
1523 // ^^^^
1524 }
1525
1526 struct Stwuct;
1527
1528 impl Twait for Stwuct {
1529 const NOMS$0: bool = true;
1530 }
1531 "#,
1532 );
1533 }
1534
1535 #[test]
1536 fn goto_def_of_trait_impl_type_alias() {
1537 check(
1538 r#"
1539 trait Twait {
1540 type IsBad;
1541 // ^^^^^
1542 }
1543
1544 struct Stwuct;
1545
1546 impl Twait for Stwuct {
1547 type IsBad$0 = !;
1548 }
1549 "#,
1550 );
1551 }
1552
1553 #[test]
1554 fn goto_def_derive_input() {
1555 check(
1556 r#"
1557 //- minicore:derive
1558 #[rustc_builtin_macro]
1559 pub macro Copy {}
1560 // ^^^^
1561 #[derive(Copy$0)]
1562 struct Foo;
1563 "#,
1564 );
1565 check(
1566 r#"
1567 //- minicore:derive
1568 #[rustc_builtin_macro]
1569 pub macro Copy {}
1570 // ^^^^
1571 #[cfg_attr(feature = "false", derive)]
1572 #[derive(Copy$0)]
1573 struct Foo;
1574 "#,
1575 );
1576 check(
1577 r#"
1578 //- minicore:derive
1579 mod foo {
1580 #[rustc_builtin_macro]
1581 pub macro Copy {}
1582 // ^^^^
1583 }
1584 #[derive(foo::Copy$0)]
1585 struct Foo;
1586 "#,
1587 );
1588 check(
1589 r#"
1590 //- minicore:derive
1591 mod foo {
1592 // ^^^
1593 #[rustc_builtin_macro]
1594 pub macro Copy {}
1595 }
1596 #[derive(foo$0::Copy)]
1597 struct Foo;
1598 "#,
1599 );
1600 }
1601
1602 #[test]
1603 fn goto_def_in_macro_multi() {
1604 check(
1605 r#"
1606 struct Foo {
1607 foo: ()
1608 //^^^
1609 }
1610 macro_rules! foo {
1611 ($ident:ident) => {
1612 fn $ident(Foo { $ident }: Foo) {}
1613 }
1614 }
1615 foo!(foo$0);
1616 //^^^
1617 //^^^
1618 "#,
1619 );
1620 check(
1621 r#"
1622 fn bar() {}
1623 //^^^
1624 struct bar;
1625 //^^^
1626 macro_rules! foo {
1627 ($ident:ident) => {
1628 fn foo() {
1629 let _: $ident = $ident;
1630 }
1631 }
1632 }
1633
1634 foo!(bar$0);
1635 "#,
1636 );
1637 }
1638
1639 #[test]
1640 fn goto_await_poll() {
1641 check(
1642 r#"
1643 //- minicore: future
1644
1645 struct MyFut;
1646
1647 impl core::future::Future for MyFut {
1648 type Output = ();
1649
1650 fn poll(
1651 //^^^^
1652 self: std::pin::Pin<&mut Self>,
1653 cx: &mut std::task::Context<'_>
1654 ) -> std::task::Poll<Self::Output>
1655 {
1656 ()
1657 }
1658 }
1659
1660 fn f() {
1661 MyFut.await$0;
1662 }
1663 "#,
1664 );
1665 }
1666
1667 #[test]
1668 fn goto_await_into_future_poll() {
1669 check(
1670 r#"
1671 //- minicore: future
1672
1673 struct Futurable;
1674
1675 impl core::future::IntoFuture for Futurable {
1676 type IntoFuture = MyFut;
1677 }
1678
1679 struct MyFut;
1680
1681 impl core::future::Future for MyFut {
1682 type Output = ();
1683
1684 fn poll(
1685 //^^^^
1686 self: std::pin::Pin<&mut Self>,
1687 cx: &mut std::task::Context<'_>
1688 ) -> std::task::Poll<Self::Output>
1689 {
1690 ()
1691 }
1692 }
1693
1694 fn f() {
1695 Futurable.await$0;
1696 }
1697 "#,
1698 );
1699 }
1700
1701 #[test]
1702 fn goto_try_op() {
1703 check(
1704 r#"
1705 //- minicore: try
1706
1707 struct Struct;
1708
1709 impl core::ops::Try for Struct {
1710 fn branch(
1711 //^^^^^^
1712 self
1713 ) {}
1714 }
1715
1716 fn f() {
1717 Struct?$0;
1718 }
1719 "#,
1720 );
1721 }
1722
1723 #[test]
1724 fn goto_index_op() {
1725 check(
1726 r#"
1727 //- minicore: index
1728
1729 struct Struct;
1730
1731 impl core::ops::Index<usize> for Struct {
1732 fn index(
1733 //^^^^^
1734 self
1735 ) {}
1736 }
1737
1738 fn f() {
1739 Struct[0]$0;
1740 }
1741 "#,
1742 );
1743 }
1744
1745 #[test]
1746 fn goto_prefix_op() {
1747 check(
1748 r#"
1749 //- minicore: deref
1750
1751 struct Struct;
1752
1753 impl core::ops::Deref for Struct {
1754 fn deref(
1755 //^^^^^
1756 self
1757 ) {}
1758 }
1759
1760 fn f() {
1761 $0*Struct;
1762 }
1763 "#,
1764 );
1765 }
1766
1767 #[test]
1768 fn goto_bin_op() {
1769 check(
1770 r#"
1771 //- minicore: add
1772
1773 struct Struct;
1774
1775 impl core::ops::Add for Struct {
1776 fn add(
1777 //^^^
1778 self
1779 ) {}
1780 }
1781
1782 fn f() {
1783 Struct +$0 Struct;
1784 }
1785 "#,
1786 );
1787 }
1788 }