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