3 defs::{classify_name, classify_name_ref},
4 symbol_index, RootDatabase,
10 SyntaxToken, TokenAtOffset, T,
14 display::{ToNav, TryToNav},
15 FilePosition, NavigationTarget, RangeInfo,
18 // Feature: Go to Definition
20 // Navigates to the definition of an identifier.
23 // | Editor | Shortcut
25 // | VS Code | kbd:[F12]
27 pub(crate) fn goto_definition(
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 = pick_best(file.token_at_offset(position.offset))?;
34 let token = sema.descend_into_macros(original_token.clone());
35 let parent = token.parent();
37 let nav_targets = match_ast! {
39 ast::NameRef(name_ref) => {
40 reference_definition(&sema, &name_ref).to_vec()
43 let def = classify_name(&sema, &name)?.definition(sema.db);
44 let nav = def.try_to_nav(sema.db)?;
51 Some(RangeInfo::new(original_token.text_range(), nav_targets))
54 fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
55 return tokens.max_by_key(priority);
56 fn priority(n: &SyntaxToken) -> usize {
58 IDENT | INT_NUMBER | T![self] => 2,
59 kind if kind.is_trivia() => 0,
66 pub(crate) enum ReferenceResult {
67 Exact(NavigationTarget),
68 Approximate(Vec<NavigationTarget>),
71 impl ReferenceResult {
72 fn to_vec(self) -> Vec<NavigationTarget> {
74 ReferenceResult::Exact(target) => vec![target],
75 ReferenceResult::Approximate(vec) => vec,
80 pub(crate) fn reference_definition(
81 sema: &Semantics<RootDatabase>,
82 name_ref: &ast::NameRef,
83 ) -> ReferenceResult {
84 let name_kind = classify_name_ref(sema, name_ref);
85 if let Some(def) = name_kind {
86 let def = def.definition(sema.db);
87 return match def.try_to_nav(sema.db) {
88 Some(nav) => ReferenceResult::Exact(nav),
89 None => ReferenceResult::Approximate(Vec::new()),
93 // Fallback index based approach:
94 let navs = symbol_index::index_resolve(sema.db, name_ref)
96 .map(|s| s.to_nav(sema.db))
98 ReferenceResult::Approximate(navs)
103 use base_db::FileRange;
104 use syntax::{TextRange, TextSize};
108 fn check(ra_fixture: &str) {
109 let (analysis, position, mut annotations) = fixture::annotations(ra_fixture);
110 let (mut expected, data) = annotations.pop().unwrap();
111 match data.as_str() {
115 TextRange::up_to(TextSize::of(&*analysis.file_text(expected.file_id).unwrap()))
117 data => panic!("bad data: {}", data),
121 analysis.goto_definition(position).unwrap().expect("no definition found").info;
123 panic!("unresolved reference")
125 assert_eq!(navs.len(), 1);
127 let nav = navs.pop().unwrap();
128 assert_eq!(expected, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() });
132 fn goto_def_for_extern_crate() {
135 //- /main.rs crate:main deps:std
137 //- /std/lib.rs crate:std
145 fn goto_def_for_renamed_extern_crate() {
148 //- /main.rs crate:main deps:std
149 extern crate std as abc<|>;
150 //- /std/lib.rs crate:std
158 fn goto_def_in_items() {
169 fn goto_def_at_start_of_item() {
180 fn goto_definition_resolves_correct_name() {
199 fn goto_def_for_module_declaration() {
224 fn goto_def_for_macros() {
227 macro_rules! foo { () => { () } }
237 fn goto_def_for_macros_from_other_crates() {
248 macro_rules! foo { () => { () } }
255 fn goto_def_for_macros_in_use_tree() {
263 macro_rules! foo { () => { () } }
270 fn goto_def_for_macro_defined_fn_with_arg() {
274 macro_rules! define_fn {
275 ($name:ident) => (fn $name() {})
289 fn goto_def_for_macro_defined_fn_no_arg() {
293 macro_rules! define_fn {
308 fn goto_definition_works_for_macro_inside_pattern() {
312 macro_rules! foo {() => {0}}
325 fn goto_definition_works_for_macro_inside_match_arm_lhs() {
329 macro_rules! foo {() => {0}}
341 fn goto_def_for_use_alias() {
344 //- /lib.rs crate:main deps:foo
347 //- /foo/lib.rs crate:foo
355 fn goto_def_for_use_alias_foo_macro() {
358 //- /lib.rs crate:main deps:foo
359 use foo::foo as bar<|>;
361 //- /foo/lib.rs crate:foo
363 macro_rules! foo { () => { () } }
370 fn goto_def_for_methods() {
375 fn frobnicate(&self) { }
387 fn goto_def_for_fields() {
402 fn goto_def_for_record_fields() {
420 fn goto_def_for_record_pat_fields() {
428 fn bar(foo: Foo) -> Foo {
429 let Foo { spam<|>: _, } = foo
436 fn goto_def_for_record_fields_macros() {
439 macro_rules! m { () => { 92 };}
440 struct Foo { spam: u32 }
444 Foo { spam<|>: m!() }
451 fn goto_for_tuple_fields() {
466 fn goto_def_for_ufcs_inherent_methods() {
475 Foo::frobnicate<|>();
482 fn goto_def_for_ufcs_trait_methods_through_traits() {
490 Foo::frobnicate<|>();
497 fn goto_def_for_ufcs_trait_methods_through_self() {
504 impl Trait for Foo {}
507 Foo::frobnicate<|>();
514 fn goto_definition_on_self() {
520 pub fn new() -> Self {
531 pub fn new() -> Self<|> {
543 pub fn new() -> Self<|> {
555 pub fn thing(a: &Self<|>) {
563 fn goto_definition_on_self_in_trait_impl() {
587 fn new() -> Self<|> {
596 fn goto_def_when_used_on_definition_name_itself() {
599 struct Foo<|> { value: u32 }
621 enum Foo<|> { Variant }
639 static INNER<|>: &str = "";
646 const INNER<|>: &str = "";
653 type Thing<|> = Option<()>;
674 fn goto_from_macro() {
678 ($($tt:tt)*) => { $($tt)* }
687 mod confuse_index { fn foo(); }
693 fn goto_through_format() {
697 macro_rules! format {
698 ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*)))
700 #[rustc_builtin_macro]
702 macro_rules! format_args {
703 ($fmt:expr) => ({ /* compiler built-in */ });
704 ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
707 pub use crate::format_args;
708 fn foo() {} // for index confusion
713 format!("{}", fo<|>o())
720 fn goto_for_type_param() {
723 struct Foo<T: Clone> { t: <|>T }
730 fn goto_within_macro() {
734 ($($tt:tt)*) => ($($tt)*)
751 ($($tt:tt)*) => ($($tt)*)
767 fn goto_def_in_local_fn() {
782 fn goto_def_in_local_macro() {
786 macro_rules! foo { () => { () } }
795 fn goto_def_for_field_init_shorthand() {
798 struct Foo { x: i32 }
809 fn goto_def_for_enum_variant_field() {
817 Foo::Bar { x<|> } => x
825 fn goto_def_for_enum_variant_self_pattern_const() {
832 match self { Self::Bar<|> => {} }
840 fn goto_def_for_enum_variant_self_pattern_record() {
843 enum Foo { Bar { val: i32 } }
846 fn baz(self) -> i32 {
847 match self { Self::Bar<|> { val } => {} }
855 fn goto_def_for_enum_variant_self_expr_const() {
861 fn baz(self) { Self::Bar<|>; }
868 fn goto_def_for_enum_variant_self_expr_record() {
871 enum Foo { Bar { val: i32 } }
874 fn baz(self) { Self::Bar<|> {val: 4}; }
881 fn goto_def_for_type_alias_generic_parameter() {
884 type Alias<T> = T<|>;
891 fn goto_def_for_macro_container() {
895 foo::module<|>::mac!();
901 macro_rules! _mac { () => { () } }
902 pub use crate::_mac as mac;
909 fn goto_def_for_assoc_ty_in_path() {
917 fn f() -> impl Iterator<Item<|> = u8> {}
923 fn goto_def_for_assoc_ty_in_path_multiple() {
932 fn f() -> impl Iterator<A<|> = u8, B = ()> {}
943 fn f() -> impl Iterator<A = u8, B<|> = ()> {}
949 fn goto_def_for_assoc_ty_ufcs() {
957 fn g() -> <() as Iterator<Item<|> = ()>>::Item {}
963 fn goto_def_for_assoc_ty_ufcs_multiple() {
972 fn g() -> <() as Iterator<A<|> = (), B = u8>>::B {}
983 fn g() -> <() as Iterator<A = (), B<|> = u8>>::A {}