1- use hir:: Semantics ;
1+ use hir:: { AsAssocItem , Semantics } ;
22use ide_db:: {
33 defs:: { Definition , NameClass , NameRefClass } ,
44 RootDatabase ,
55} ;
66use syntax:: { ast, match_ast, AstNode , SyntaxKind :: * , T } ;
77
8- use crate :: { FilePosition , NavigationTarget , RangeInfo } ;
8+ use crate :: {
9+ goto_definition:: goto_definition, navigation_target:: TryToNav , FilePosition , NavigationTarget ,
10+ RangeInfo ,
11+ } ;
912
1013// Feature: Go to Declaration
1114//
1215// Navigates to the declaration of an identifier.
1316//
14- // This is currently the same as `Go to Definition` with the exception of outline modules where it
15- // will navigate to the `mod name;` item declaration.
17+ // This is the same as `Go to Definition` with the following exceptions:
18+ // - outline modules will navigate to the `mod name;` item declaration
19+ // - trait assoc items will navigate to the assoc item of the trait declaration opposed to the trait impl
1620pub ( crate ) fn goto_declaration (
1721 db : & RootDatabase ,
1822 position : FilePosition ,
@@ -32,25 +36,37 @@ pub(crate) fn goto_declaration(
3236 match parent {
3337 ast:: NameRef ( name_ref) => match NameRefClass :: classify( & sema, & name_ref) ? {
3438 NameRefClass :: Definition ( it) => Some ( it) ,
35- _ => None
39+ NameRefClass :: FieldShorthand { field_ref , .. } => return field_ref . try_to_nav ( db ) ,
3640 } ,
3741 ast:: Name ( name) => match NameClass :: classify( & sema, & name) ? {
38- NameClass :: Definition ( it) => Some ( it) ,
39- _ => None
42+ NameClass :: Definition ( it) | NameClass :: ConstReference ( it ) => Some ( it) ,
43+ NameClass :: PatFieldShorthand { field_ref , .. } => return field_ref . try_to_nav ( db ) ,
4044 } ,
4145 _ => None
4246 }
4347 } ;
44- match def? {
48+ let assoc = match def? {
4549 Definition :: Module ( module) => {
46- Some ( NavigationTarget :: from_module_to_decl ( db, module) )
50+ return Some ( NavigationTarget :: from_module_to_decl ( db, module) )
4751 }
52+ Definition :: Const ( c) => c. as_assoc_item ( db) ,
53+ Definition :: TypeAlias ( ta) => ta. as_assoc_item ( db) ,
54+ Definition :: Function ( f) => f. as_assoc_item ( db) ,
4855 _ => None ,
49- }
56+ } ?;
57+
58+ let trait_ = assoc. containing_trait_impl ( db) ?;
59+ let name = Some ( assoc. name ( db) ?) ;
60+ let item = trait_. items ( db) . into_iter ( ) . find ( |it| it. name ( db) == name) ?;
61+ item. try_to_nav ( db)
5062 } )
5163 . collect ( ) ;
5264
53- Some ( RangeInfo :: new ( range, info) )
65+ if info. is_empty ( ) {
66+ goto_definition ( db, position)
67+ } else {
68+ Some ( RangeInfo :: new ( range, info) )
69+ }
5470}
5571
5672#[ cfg( test) ]
@@ -109,4 +125,89 @@ mod foo {
109125"# ,
110126 )
111127 }
128+
129+ #[ test]
130+ fn goto_decl_goto_def_fallback ( ) {
131+ check (
132+ r#"
133+ struct Foo;
134+ // ^^^
135+ impl Foo$0 {}
136+ "# ,
137+ ) ;
138+ }
139+
140+ #[ test]
141+ fn goto_decl_assoc_item_no_impl_item ( ) {
142+ check (
143+ r#"
144+ trait Trait {
145+ const C: () = ();
146+ // ^
147+ }
148+ impl Trait for () {}
149+
150+ fn main() {
151+ <()>::C$0;
152+ }
153+ "# ,
154+ ) ;
155+ }
156+
157+ #[ test]
158+ fn goto_decl_assoc_item ( ) {
159+ check (
160+ r#"
161+ trait Trait {
162+ const C: () = ();
163+ // ^
164+ }
165+ impl Trait for () {
166+ const C: () = ();
167+ }
168+
169+ fn main() {
170+ <()>::C$0;
171+ }
172+ "# ,
173+ ) ;
174+ check (
175+ r#"
176+ trait Trait {
177+ const C: () = ();
178+ // ^
179+ }
180+ impl Trait for () {
181+ const C$0: () = ();
182+ }
183+ "# ,
184+ ) ;
185+ }
186+
187+ #[ test]
188+ fn goto_decl_field_pat_shorthand ( ) {
189+ check (
190+ r#"
191+ struct Foo { field: u32 }
192+ //^^^^^
193+ fn main() {
194+ let Foo { field$0 };
195+ }
196+ "# ,
197+ ) ;
198+ }
199+
200+ #[ test]
201+ fn goto_decl_constructor_shorthand ( ) {
202+ check (
203+ r#"
204+ struct Foo { field: u32 }
205+ //^^^^^
206+ fn main() {
207+ let field = 0;
208+ Foo { field$0 };
209+ }
210+ "# ,
211+ ) ;
212+ }
112213}
0 commit comments