diff options
author | Ville Penttinen <[email protected]> | 2019-02-27 15:22:53 +0000 |
---|---|---|
committer | Ville Penttinen <[email protected]> | 2019-02-27 15:51:59 +0000 |
commit | bb4521be1cbf10712804bb1e2dadbdfbf942437a (patch) | |
tree | 9c1ab5b302d6d95c772b827d5a491fa0e331df92 | |
parent | 2e2a6dd2fbeb4da16e602fa1902ab6bbd850b442 (diff) |
Allow goto-definition to work for named fields in struct initializer
Now goto definition should work when done on a named field in a struct
initializer.
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 44 | ||||
-rw-r--r-- | crates/ra_ide_api/src/marks.rs | 1 |
2 files changed, 45 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index da33739be..6fa430754 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -74,6 +74,30 @@ pub(crate) fn reference_definition( | |||
74 | return Exact(NavigationTarget::from_field(db, field)); | 74 | return Exact(NavigationTarget::from_field(db, field)); |
75 | }; | 75 | }; |
76 | } | 76 | } |
77 | |||
78 | // It could also be a named field | ||
79 | if let Some(field_expr) = name_ref.syntax().parent().and_then(ast::NamedField::cast) { | ||
80 | tested_by!(goto_definition_works_for_named_fields); | ||
81 | |||
82 | let infer_result = function.infer(db); | ||
83 | let syntax_mapping = function.body_syntax_mapping(db); | ||
84 | |||
85 | let struct_lit = field_expr.syntax().ancestors().find_map(ast::StructLit::cast); | ||
86 | |||
87 | if let Some(expr) = struct_lit.and_then(|lit| syntax_mapping.node_expr(lit.into())) { | ||
88 | let ty = infer_result[expr].clone(); | ||
89 | if let hir::Ty::Adt { def_id, .. } = ty { | ||
90 | if let hir::AdtDef::Struct(s) = def_id { | ||
91 | let hir_path = hir::Path::from_name_ref(name_ref); | ||
92 | let hir_name = hir_path.as_ident().unwrap(); | ||
93 | |||
94 | if let Some(field) = s.field(db, hir_name) { | ||
95 | return Exact(NavigationTarget::from_field(db, field)); | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | } | ||
77 | } | 101 | } |
78 | // Try name resolution | 102 | // Try name resolution |
79 | let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax()); | 103 | let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax()); |
@@ -256,6 +280,26 @@ mod tests { | |||
256 | } | 280 | } |
257 | 281 | ||
258 | #[test] | 282 | #[test] |
283 | fn goto_definition_works_for_named_fields() { | ||
284 | covers!(goto_definition_works_for_named_fields); | ||
285 | check_goto( | ||
286 | " | ||
287 | //- /lib.rs | ||
288 | struct Foo { | ||
289 | spam: u32, | ||
290 | } | ||
291 | |||
292 | fn bar() -> Foo { | ||
293 | Foo { | ||
294 | spam<|>: 0, | ||
295 | } | ||
296 | } | ||
297 | ", | ||
298 | "spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)", | ||
299 | ); | ||
300 | } | ||
301 | |||
302 | #[test] | ||
259 | fn goto_definition_works_when_used_on_definition_name_itself() { | 303 | fn goto_definition_works_when_used_on_definition_name_itself() { |
260 | check_goto( | 304 | check_goto( |
261 | " | 305 | " |
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs index 44d8fdf82..bcbe0d21b 100644 --- a/crates/ra_ide_api/src/marks.rs +++ b/crates/ra_ide_api/src/marks.rs | |||
@@ -2,6 +2,7 @@ test_utils::marks!( | |||
2 | inserts_parens_for_function_calls | 2 | inserts_parens_for_function_calls |
3 | goto_definition_works_for_methods | 3 | goto_definition_works_for_methods |
4 | goto_definition_works_for_fields | 4 | goto_definition_works_for_fields |
5 | goto_definition_works_for_named_fields | ||
5 | call_info_bad_offset | 6 | call_info_bad_offset |
6 | dont_complete_current_use | 7 | dont_complete_current_use |
7 | ); | 8 | ); |