1
- use hir:: Semantics ;
1
+ use hir:: { AsAssocItem , Semantics } ;
2
2
use ide_db:: {
3
3
defs:: { Definition , NameClass , NameRefClass } ,
4
4
RootDatabase ,
5
5
} ;
6
6
use syntax:: { ast, match_ast, AstNode , SyntaxKind :: * , T } ;
7
7
8
- use crate :: { FilePosition , NavigationTarget , RangeInfo } ;
8
+ use crate :: {
9
+ goto_definition:: goto_definition, navigation_target:: TryToNav , FilePosition , NavigationTarget ,
10
+ RangeInfo ,
11
+ } ;
9
12
10
13
// Feature: Go to Declaration
11
14
//
12
15
// Navigates to the declaration of an identifier.
13
16
//
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
16
20
pub ( crate ) fn goto_declaration (
17
21
db : & RootDatabase ,
18
22
position : FilePosition ,
@@ -32,25 +36,37 @@ pub(crate) fn goto_declaration(
32
36
match parent {
33
37
ast:: NameRef ( name_ref) => match NameRefClass :: classify( & sema, & name_ref) ? {
34
38
NameRefClass :: Definition ( it) => Some ( it) ,
35
- _ => None
39
+ NameRefClass :: FieldShorthand { field_ref , .. } => return field_ref . try_to_nav ( db ) ,
36
40
} ,
37
41
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 ) ,
40
44
} ,
41
45
_ => None
42
46
}
43
47
} ;
44
- match def? {
48
+ let assoc = match def? {
45
49
Definition :: Module ( module) => {
46
- Some ( NavigationTarget :: from_module_to_decl ( db, module) )
50
+ return Some ( NavigationTarget :: from_module_to_decl ( db, module) )
47
51
}
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) ,
48
55
_ => 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)
50
62
} )
51
63
. collect ( ) ;
52
64
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
+ }
54
70
}
55
71
56
72
#[ cfg( test) ]
@@ -109,4 +125,89 @@ mod foo {
109
125
"# ,
110
126
)
111
127
}
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
+ }
112
213
}
0 commit comments