]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/goto_definition.rs
don't clone types that are copy (clippy::clone_on_copy)
[rust.git] / crates / ide / src / goto_definition.rs
1 use either::Either;
2 use hir::{HasAttrs, ModuleDef, Semantics};
3 use ide_db::{
4     defs::{Definition, NameClass, NameRefClass},
5     RootDatabase,
6 };
7 use syntax::{
8     ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextSize, TokenAtOffset, T,
9 };
10
11 use crate::{
12     display::TryToNav, doc_links::extract_definitions_from_markdown, runnables::doc_owner_to_def,
13     FilePosition, NavigationTarget, RangeInfo,
14 };
15
16 // Feature: Go to Definition
17 //
18 // Navigates to the definition of an identifier.
19 //
20 // |===
21 // | Editor  | Shortcut
22 //
23 // | VS Code | kbd:[F12]
24 // |===
25 pub(crate) fn goto_definition(
26     db: &RootDatabase,
27     position: FilePosition,
28 ) -> Option<RangeInfo<Vec<NavigationTarget>>> {
29     let sema = Semantics::new(db);
30     let file = sema.parse(position.file_id).syntax().clone();
31     let original_token = pick_best(file.token_at_offset(position.offset))?;
32     let token = sema.descend_into_macros(original_token.clone());
33     let parent = token.parent()?;
34     if let Some(comment) = ast::Comment::cast(token) {
35         let nav = def_for_doc_comment(&sema, position, &comment)?.try_to_nav(db)?;
36         return Some(RangeInfo::new(original_token.text_range(), vec![nav]));
37     }
38
39     let nav = match_ast! {
40         match parent {
41             ast::NameRef(name_ref) => {
42                 reference_definition(&sema, Either::Right(&name_ref))
43             },
44             ast::Name(name) => {
45                 let def = NameClass::classify(&sema, &name)?.referenced_or_defined(sema.db);
46                 def.try_to_nav(sema.db)
47             },
48             ast::Lifetime(lt) => if let Some(name_class) = NameClass::classify_lifetime(&sema, &lt) {
49                 let def = name_class.referenced_or_defined(sema.db);
50                 def.try_to_nav(sema.db)
51             } else {
52                 reference_definition(&sema, Either::Left(&lt))
53             },
54             _ => return None,
55         }
56     };
57
58     Some(RangeInfo::new(original_token.text_range(), nav.into_iter().collect()))
59 }
60
61 fn def_for_doc_comment(
62     sema: &Semantics<RootDatabase>,
63     position: FilePosition,
64     doc_comment: &ast::Comment,
65 ) -> Option<hir::ModuleDef> {
66     let parent = doc_comment.syntax().parent()?;
67     let (link, ns) = extract_positioned_link_from_comment(position, doc_comment)?;
68
69     let def = doc_owner_to_def(sema, parent)?;
70     match def {
71         Definition::ModuleDef(def) => match def {
72             ModuleDef::Module(it) => it.resolve_doc_path(sema.db, &link, ns),
73             ModuleDef::Function(it) => it.resolve_doc_path(sema.db, &link, ns),
74             ModuleDef::Adt(it) => it.resolve_doc_path(sema.db, &link, ns),
75             ModuleDef::Variant(it) => it.resolve_doc_path(sema.db, &link, ns),
76             ModuleDef::Const(it) => it.resolve_doc_path(sema.db, &link, ns),
77             ModuleDef::Static(it) => it.resolve_doc_path(sema.db, &link, ns),
78             ModuleDef::Trait(it) => it.resolve_doc_path(sema.db, &link, ns),
79             ModuleDef::TypeAlias(it) => it.resolve_doc_path(sema.db, &link, ns),
80             ModuleDef::BuiltinType(_) => return None,
81         },
82         Definition::Macro(it) => it.resolve_doc_path(sema.db, &link, ns),
83         Definition::Field(it) => it.resolve_doc_path(sema.db, &link, ns),
84         Definition::SelfType(_)
85         | Definition::Local(_)
86         | Definition::GenericParam(_)
87         | Definition::Label(_) => return None,
88     }
89 }
90
91 fn extract_positioned_link_from_comment(
92     position: FilePosition,
93     comment: &ast::Comment,
94 ) -> Option<(String, Option<hir::Namespace>)> {
95     let comment_range = comment.syntax().text_range();
96     let doc_comment = comment.doc_comment()?;
97     let def_links = extract_definitions_from_markdown(doc_comment);
98     let (def_link, ns, _) = def_links.iter().min_by_key(|(_, _, def_link_range)| {
99         let matched_position = comment_range.start() + TextSize::from(def_link_range.start as u32);
100         match position.offset.checked_sub(matched_position) {
101             Some(distance) => distance,
102             None => comment_range.end(),
103         }
104     })?;
105     Some((def_link.to_string(), *ns))
106 }
107
108 fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
109     return tokens.max_by_key(priority);
110     fn priority(n: &SyntaxToken) -> usize {
111         match n.kind() {
112             IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | COMMENT => 2,
113             kind if kind.is_trivia() => 0,
114             _ => 1,
115         }
116     }
117 }
118
119 pub(crate) fn reference_definition(
120     sema: &Semantics<RootDatabase>,
121     name_ref: Either<&ast::Lifetime, &ast::NameRef>,
122 ) -> Option<NavigationTarget> {
123     let name_kind = name_ref.either(
124         |lifetime| NameRefClass::classify_lifetime(sema, lifetime),
125         |name_ref| NameRefClass::classify(sema, name_ref),
126     )?;
127     let def = name_kind.referenced(sema.db);
128     def.try_to_nav(sema.db)
129 }
130
131 #[cfg(test)]
132 mod tests {
133     use ide_db::base_db::FileRange;
134
135     use crate::fixture;
136
137     fn check(ra_fixture: &str) {
138         let (analysis, position, expected) = fixture::nav_target_annotation(ra_fixture);
139         let mut navs =
140             analysis.goto_definition(position).unwrap().expect("no definition found").info;
141         if navs.len() == 0 {
142             panic!("unresolved reference")
143         }
144         assert_eq!(navs.len(), 1);
145
146         let nav = navs.pop().unwrap();
147         assert_eq!(expected, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() });
148     }
149
150     #[test]
151     fn goto_def_for_extern_crate() {
152         check(
153             r#"
154 //- /main.rs crate:main deps:std
155 extern crate std$0;
156 //- /std/lib.rs crate:std
157 // empty
158 //^ file
159 "#,
160         )
161     }
162
163     #[test]
164     fn goto_def_for_renamed_extern_crate() {
165         check(
166             r#"
167 //- /main.rs crate:main deps:std
168 extern crate std as abc$0;
169 //- /std/lib.rs crate:std
170 // empty
171 //^ file
172 "#,
173         )
174     }
175
176     #[test]
177     fn goto_def_in_items() {
178         check(
179             r#"
180 struct Foo;
181      //^^^
182 enum E { X(Foo$0) }
183 "#,
184         );
185     }
186
187     #[test]
188     fn goto_def_at_start_of_item() {
189         check(
190             r#"
191 struct Foo;
192      //^^^
193 enum E { X($0Foo) }
194 "#,
195         );
196     }
197
198     #[test]
199     fn goto_definition_resolves_correct_name() {
200         check(
201             r#"
202 //- /lib.rs
203 use a::Foo;
204 mod a;
205 mod b;
206 enum E { X(Foo$0) }
207
208 //- /a.rs
209 struct Foo;
210      //^^^
211 //- /b.rs
212 struct Foo;
213 "#,
214         );
215     }
216
217     #[test]
218     fn goto_def_for_module_declaration() {
219         check(
220             r#"
221 //- /lib.rs
222 mod $0foo;
223
224 //- /foo.rs
225 // empty
226 //^ file
227 "#,
228         );
229
230         check(
231             r#"
232 //- /lib.rs
233 mod $0foo;
234
235 //- /foo/mod.rs
236 // empty
237 //^ file
238 "#,
239         );
240     }
241
242     #[test]
243     fn goto_def_for_macros() {
244         check(
245             r#"
246 macro_rules! foo { () => { () } }
247            //^^^
248 fn bar() {
249     $0foo!();
250 }
251 "#,
252         );
253     }
254
255     #[test]
256     fn goto_def_for_macros_from_other_crates() {
257         check(
258             r#"
259 //- /lib.rs crate:main deps:foo
260 use foo::foo;
261 fn bar() {
262     $0foo!();
263 }
264
265 //- /foo/lib.rs crate:foo
266 #[macro_export]
267 macro_rules! foo { () => { () } }
268            //^^^
269 "#,
270         );
271     }
272
273     #[test]
274     fn goto_def_for_macros_in_use_tree() {
275         check(
276             r#"
277 //- /lib.rs crate:main deps:foo
278 use foo::foo$0;
279
280 //- /foo/lib.rs crate:foo
281 #[macro_export]
282 macro_rules! foo { () => { () } }
283            //^^^
284 "#,
285         );
286     }
287
288     #[test]
289     fn goto_def_for_macro_defined_fn_with_arg() {
290         check(
291             r#"
292 //- /lib.rs
293 macro_rules! define_fn {
294     ($name:ident) => (fn $name() {})
295 }
296
297 define_fn!(foo);
298          //^^^
299
300 fn bar() {
301    $0foo();
302 }
303 "#,
304         );
305     }
306
307     #[test]
308     fn goto_def_for_macro_defined_fn_no_arg() {
309         check(
310             r#"
311 //- /lib.rs
312 macro_rules! define_fn {
313     () => (fn foo() {})
314 }
315
316   define_fn!();
317 //^^^^^^^^^^^^^
318
319 fn bar() {
320    $0foo();
321 }
322 "#,
323         );
324     }
325
326     #[test]
327     fn goto_definition_works_for_macro_inside_pattern() {
328         check(
329             r#"
330 //- /lib.rs
331 macro_rules! foo {() => {0}}
332            //^^^
333
334 fn bar() {
335     match (0,1) {
336         ($0foo!(), _) => {}
337     }
338 }
339 "#,
340         );
341     }
342
343     #[test]
344     fn goto_definition_works_for_macro_inside_match_arm_lhs() {
345         check(
346             r#"
347 //- /lib.rs
348 macro_rules! foo {() => {0}}
349            //^^^
350 fn bar() {
351     match 0 {
352         $0foo!() => {}
353     }
354 }
355 "#,
356         );
357     }
358
359     #[test]
360     fn goto_def_for_use_alias() {
361         check(
362             r#"
363 //- /lib.rs crate:main deps:foo
364 use foo as bar$0;
365
366 //- /foo/lib.rs crate:foo
367 // empty
368 //^ file
369 "#,
370         );
371     }
372
373     #[test]
374     fn goto_def_for_use_alias_foo_macro() {
375         check(
376             r#"
377 //- /lib.rs crate:main deps:foo
378 use foo::foo as bar$0;
379
380 //- /foo/lib.rs crate:foo
381 #[macro_export]
382 macro_rules! foo { () => { () } }
383            //^^^
384 "#,
385         );
386     }
387
388     #[test]
389     fn goto_def_for_methods() {
390         check(
391             r#"
392 struct Foo;
393 impl Foo {
394     fn frobnicate(&self) { }
395      //^^^^^^^^^^
396 }
397
398 fn bar(foo: &Foo) {
399     foo.frobnicate$0();
400 }
401 "#,
402         );
403     }
404
405     #[test]
406     fn goto_def_for_fields() {
407         check(
408             r#"
409 struct Foo {
410     spam: u32,
411 } //^^^^
412
413 fn bar(foo: &Foo) {
414     foo.spam$0;
415 }
416 "#,
417         );
418     }
419
420     #[test]
421     fn goto_def_for_record_fields() {
422         check(
423             r#"
424 //- /lib.rs
425 struct Foo {
426     spam: u32,
427 } //^^^^
428
429 fn bar() -> Foo {
430     Foo {
431         spam$0: 0,
432     }
433 }
434 "#,
435         );
436     }
437
438     #[test]
439     fn goto_def_for_record_pat_fields() {
440         check(
441             r#"
442 //- /lib.rs
443 struct Foo {
444     spam: u32,
445 } //^^^^
446
447 fn bar(foo: Foo) -> Foo {
448     let Foo { spam$0: _, } = foo
449 }
450 "#,
451         );
452     }
453
454     #[test]
455     fn goto_def_for_record_fields_macros() {
456         check(
457             r"
458 macro_rules! m { () => { 92 };}
459 struct Foo { spam: u32 }
460            //^^^^
461
462 fn bar() -> Foo {
463     Foo { spam$0: m!() }
464 }
465 ",
466         );
467     }
468
469     #[test]
470     fn goto_for_tuple_fields() {
471         check(
472             r#"
473 struct Foo(u32);
474          //^^^
475
476 fn bar() {
477     let foo = Foo(0);
478     foo.$00;
479 }
480 "#,
481         );
482     }
483
484     #[test]
485     fn goto_def_for_ufcs_inherent_methods() {
486         check(
487             r#"
488 struct Foo;
489 impl Foo {
490     fn frobnicate() { }
491 }    //^^^^^^^^^^
492
493 fn bar(foo: &Foo) {
494     Foo::frobnicate$0();
495 }
496 "#,
497         );
498     }
499
500     #[test]
501     fn goto_def_for_ufcs_trait_methods_through_traits() {
502         check(
503             r#"
504 trait Foo {
505     fn frobnicate();
506 }    //^^^^^^^^^^
507
508 fn bar() {
509     Foo::frobnicate$0();
510 }
511 "#,
512         );
513     }
514
515     #[test]
516     fn goto_def_for_ufcs_trait_methods_through_self() {
517         check(
518             r#"
519 struct Foo;
520 trait Trait {
521     fn frobnicate();
522 }    //^^^^^^^^^^
523 impl Trait for Foo {}
524
525 fn bar() {
526     Foo::frobnicate$0();
527 }
528 "#,
529         );
530     }
531
532     #[test]
533     fn goto_definition_on_self() {
534         check(
535             r#"
536 struct Foo;
537 impl Foo {
538    //^^^
539     pub fn new() -> Self {
540         Self$0 {}
541     }
542 }
543 "#,
544         );
545         check(
546             r#"
547 struct Foo;
548 impl Foo {
549    //^^^
550     pub fn new() -> Self$0 {
551         Self {}
552     }
553 }
554 "#,
555         );
556
557         check(
558             r#"
559 enum Foo { A }
560 impl Foo {
561    //^^^
562     pub fn new() -> Self$0 {
563         Foo::A
564     }
565 }
566 "#,
567         );
568
569         check(
570             r#"
571 enum Foo { A }
572 impl Foo {
573    //^^^
574     pub fn thing(a: &Self$0) {
575     }
576 }
577 "#,
578         );
579     }
580
581     #[test]
582     fn goto_definition_on_self_in_trait_impl() {
583         check(
584             r#"
585 struct Foo;
586 trait Make {
587     fn new() -> Self;
588 }
589 impl Make for Foo {
590             //^^^
591     fn new() -> Self {
592         Self$0 {}
593     }
594 }
595 "#,
596         );
597
598         check(
599             r#"
600 struct Foo;
601 trait Make {
602     fn new() -> Self;
603 }
604 impl Make for Foo {
605             //^^^
606     fn new() -> Self$0 {
607         Self {}
608     }
609 }
610 "#,
611         );
612     }
613
614     #[test]
615     fn goto_def_when_used_on_definition_name_itself() {
616         check(
617             r#"
618 struct Foo$0 { value: u32 }
619      //^^^
620             "#,
621         );
622
623         check(
624             r#"
625 struct Foo {
626     field$0: string,
627 } //^^^^^
628 "#,
629         );
630
631         check(
632             r#"
633 fn foo_test$0() { }
634  //^^^^^^^^
635 "#,
636         );
637
638         check(
639             r#"
640 enum Foo$0 { Variant }
641    //^^^
642 "#,
643         );
644
645         check(
646             r#"
647 enum Foo {
648     Variant1,
649     Variant2$0,
650   //^^^^^^^^
651     Variant3,
652 }
653 "#,
654         );
655
656         check(
657             r#"
658 static INNER$0: &str = "";
659      //^^^^^
660 "#,
661         );
662
663         check(
664             r#"
665 const INNER$0: &str = "";
666     //^^^^^
667 "#,
668         );
669
670         check(
671             r#"
672 type Thing$0 = Option<()>;
673    //^^^^^
674 "#,
675         );
676
677         check(
678             r#"
679 trait Foo$0 { }
680     //^^^
681 "#,
682         );
683
684         check(
685             r#"
686 mod bar$0 { }
687   //^^^
688 "#,
689         );
690     }
691
692     #[test]
693     fn goto_from_macro() {
694         check(
695             r#"
696 macro_rules! id {
697     ($($tt:tt)*) => { $($tt)* }
698 }
699 fn foo() {}
700  //^^^
701 id! {
702     fn bar() {
703         fo$0o();
704     }
705 }
706 mod confuse_index { fn foo(); }
707 "#,
708         );
709     }
710
711     #[test]
712     fn goto_through_format() {
713         check(
714             r#"
715 #[macro_export]
716 macro_rules! format {
717     ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*)))
718 }
719 #[rustc_builtin_macro]
720 #[macro_export]
721 macro_rules! format_args {
722     ($fmt:expr) => ({ /* compiler built-in */ });
723     ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
724 }
725 pub mod __export {
726     pub use crate::format_args;
727     fn foo() {} // for index confusion
728 }
729 fn foo() -> i8 {}
730  //^^^
731 fn test() {
732     format!("{}", fo$0o())
733 }
734 "#,
735         );
736     }
737
738     #[test]
739     fn goto_through_included_file() {
740         check(
741             r#"
742 //- /main.rs
743 #[rustc_builtin_macro]
744 macro_rules! include {}
745
746   include!("foo.rs");
747 //^^^^^^^^^^^^^^^^^^^
748
749 fn f() {
750     foo$0();
751 }
752
753 mod confuse_index {
754     pub fn foo() {}
755 }
756
757 //- /foo.rs
758 fn foo() {}
759         "#,
760         );
761     }
762
763     #[test]
764     fn goto_for_type_param() {
765         check(
766             r#"
767 struct Foo<T: Clone> { t: $0T }
768          //^
769 "#,
770         );
771     }
772
773     #[test]
774     fn goto_within_macro() {
775         check(
776             r#"
777 macro_rules! id {
778     ($($tt:tt)*) => ($($tt)*)
779 }
780
781 fn foo() {
782     let x = 1;
783       //^
784     id!({
785         let y = $0x;
786         let z = y;
787     });
788 }
789 "#,
790         );
791
792         check(
793             r#"
794 macro_rules! id {
795     ($($tt:tt)*) => ($($tt)*)
796 }
797
798 fn foo() {
799     let x = 1;
800     id!({
801         let y = x;
802           //^
803         let z = $0y;
804     });
805 }
806 "#,
807         );
808     }
809
810     #[test]
811     fn goto_def_in_local_fn() {
812         check(
813             r#"
814 fn main() {
815     fn foo() {
816         let x = 92;
817           //^
818         $0x;
819     }
820 }
821 "#,
822         );
823     }
824
825     #[test]
826     fn goto_def_in_local_macro() {
827         check(
828             r#"
829 fn bar() {
830     macro_rules! foo { () => { () } }
831                //^^^
832     $0foo!();
833 }
834 "#,
835         );
836     }
837
838     #[test]
839     fn goto_def_for_field_init_shorthand() {
840         check(
841             r#"
842 struct Foo { x: i32 }
843 fn main() {
844     let x = 92;
845       //^
846     Foo { x$0 };
847 }
848 "#,
849         )
850     }
851
852     #[test]
853     fn goto_def_for_enum_variant_field() {
854         check(
855             r#"
856 enum Foo {
857     Bar { x: i32 }
858 }       //^
859 fn baz(foo: Foo) {
860     match foo {
861         Foo::Bar { x$0 } => x
862     };
863 }
864 "#,
865         );
866     }
867
868     #[test]
869     fn goto_def_for_enum_variant_self_pattern_const() {
870         check(
871             r#"
872 enum Foo { Bar }
873          //^^^
874 impl Foo {
875     fn baz(self) {
876         match self { Self::Bar$0 => {} }
877     }
878 }
879 "#,
880         );
881     }
882
883     #[test]
884     fn goto_def_for_enum_variant_self_pattern_record() {
885         check(
886             r#"
887 enum Foo { Bar { val: i32 } }
888          //^^^
889 impl Foo {
890     fn baz(self) -> i32 {
891         match self { Self::Bar$0 { val } => {} }
892     }
893 }
894 "#,
895         );
896     }
897
898     #[test]
899     fn goto_def_for_enum_variant_self_expr_const() {
900         check(
901             r#"
902 enum Foo { Bar }
903          //^^^
904 impl Foo {
905     fn baz(self) { Self::Bar$0; }
906 }
907 "#,
908         );
909     }
910
911     #[test]
912     fn goto_def_for_enum_variant_self_expr_record() {
913         check(
914             r#"
915 enum Foo { Bar { val: i32 } }
916          //^^^
917 impl Foo {
918     fn baz(self) { Self::Bar$0 {val: 4}; }
919 }
920 "#,
921         );
922     }
923
924     #[test]
925     fn goto_def_for_type_alias_generic_parameter() {
926         check(
927             r#"
928 type Alias<T> = T$0;
929          //^
930 "#,
931         )
932     }
933
934     #[test]
935     fn goto_def_for_macro_container() {
936         check(
937             r#"
938 //- /lib.rs crate:main deps:foo
939 foo::module$0::mac!();
940
941 //- /foo/lib.rs crate:foo
942 pub mod module {
943       //^^^^^^
944     #[macro_export]
945     macro_rules! _mac { () => { () } }
946     pub use crate::_mac as mac;
947 }
948 "#,
949         );
950     }
951
952     #[test]
953     fn goto_def_for_assoc_ty_in_path() {
954         check(
955             r#"
956 trait Iterator {
957     type Item;
958        //^^^^
959 }
960
961 fn f() -> impl Iterator<Item$0 = u8> {}
962 "#,
963         );
964     }
965
966     #[test]
967     fn goto_def_for_assoc_ty_in_path_multiple() {
968         check(
969             r#"
970 trait Iterator {
971     type A;
972        //^
973     type B;
974 }
975
976 fn f() -> impl Iterator<A$0 = u8, B = ()> {}
977 "#,
978         );
979         check(
980             r#"
981 trait Iterator {
982     type A;
983     type B;
984        //^
985 }
986
987 fn f() -> impl Iterator<A = u8, B$0 = ()> {}
988 "#,
989         );
990     }
991
992     #[test]
993     fn goto_def_for_assoc_ty_ufcs() {
994         check(
995             r#"
996 trait Iterator {
997     type Item;
998        //^^^^
999 }
1000
1001 fn g() -> <() as Iterator<Item$0 = ()>>::Item {}
1002 "#,
1003         );
1004     }
1005
1006     #[test]
1007     fn goto_def_for_assoc_ty_ufcs_multiple() {
1008         check(
1009             r#"
1010 trait Iterator {
1011     type A;
1012        //^
1013     type B;
1014 }
1015
1016 fn g() -> <() as Iterator<A$0 = (), B = u8>>::B {}
1017 "#,
1018         );
1019         check(
1020             r#"
1021 trait Iterator {
1022     type A;
1023     type B;
1024        //^
1025 }
1026
1027 fn g() -> <() as Iterator<A = (), B$0 = u8>>::A {}
1028 "#,
1029         );
1030     }
1031
1032     #[test]
1033     fn goto_self_param_ty_specified() {
1034         check(
1035             r#"
1036 struct Foo {}
1037
1038 impl Foo {
1039     fn bar(self: &Foo) {
1040          //^^^^
1041         let foo = sel$0f;
1042     }
1043 }"#,
1044         )
1045     }
1046
1047     #[test]
1048     fn goto_self_param_on_decl() {
1049         check(
1050             r#"
1051 struct Foo {}
1052
1053 impl Foo {
1054     fn bar(&self$0) {
1055           //^^^^
1056     }
1057 }"#,
1058         )
1059     }
1060
1061     #[test]
1062     fn goto_lifetime_param_on_decl() {
1063         check(
1064             r#"
1065 fn foo<'foobar$0>(_: &'foobar ()) {
1066      //^^^^^^^
1067 }"#,
1068         )
1069     }
1070
1071     #[test]
1072     fn goto_lifetime_param_decl() {
1073         check(
1074             r#"
1075 fn foo<'foobar>(_: &'foobar$0 ()) {
1076      //^^^^^^^
1077 }"#,
1078         )
1079     }
1080
1081     #[test]
1082     fn goto_lifetime_param_decl_nested() {
1083         check(
1084             r#"
1085 fn foo<'foobar>(_: &'foobar ()) {
1086     fn foo<'foobar>(_: &'foobar$0 ()) {}
1087          //^^^^^^^
1088 }"#,
1089         )
1090     }
1091
1092     #[test]
1093     #[ignore] // requires the HIR to somehow track these hrtb lifetimes
1094     fn goto_lifetime_hrtb() {
1095         check(
1096             r#"trait Foo<T> {}
1097 fn foo<T>() where for<'a> T: Foo<&'a$0 (u8, u16)>, {}
1098                     //^^
1099 "#,
1100         );
1101         check(
1102             r#"trait Foo<T> {}
1103 fn foo<T>() where for<'a$0> T: Foo<&'a (u8, u16)>, {}
1104                     //^^
1105 "#,
1106         );
1107     }
1108
1109     #[test]
1110     #[ignore] // requires ForTypes to be implemented
1111     fn goto_lifetime_hrtb_for_type() {
1112         check(
1113             r#"trait Foo<T> {}
1114 fn foo<T>() where T: for<'a> Foo<&'a$0 (u8, u16)>, {}
1115                        //^^
1116 "#,
1117         );
1118     }
1119
1120     #[test]
1121     fn goto_label() {
1122         check(
1123             r#"
1124 fn foo<'foo>(_: &'foo ()) {
1125     'foo: {
1126   //^^^^
1127         'bar: loop {
1128             break 'foo$0;
1129         }
1130     }
1131 }"#,
1132         )
1133     }
1134
1135     #[test]
1136     fn goto_def_for_intra_doc_link_same_file() {
1137         check(
1138             r#"
1139 /// Blah, [`bar`](bar) .. [`foo`](foo)$0 has [`bar`](bar)
1140 pub fn bar() { }
1141
1142 /// You might want to see [`std::fs::read()`] too.
1143 pub fn foo() { }
1144      //^^^
1145
1146 }"#,
1147         )
1148     }
1149
1150     #[test]
1151     fn goto_def_for_intra_doc_link_inner() {
1152         check(
1153             r#"
1154 //- /main.rs
1155 mod m;
1156 struct S;
1157      //^
1158
1159 //- /m.rs
1160 //! [`super::S$0`]
1161 "#,
1162         )
1163     }
1164
1165     #[test]
1166     fn goto_incomplete_field() {
1167         check(
1168             r#"
1169 struct A { a: u32 }
1170          //^
1171 fn foo() { A { a$0: }; }
1172 "#,
1173         )
1174     }
1175 }