aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVille Penttinen <[email protected]>2019-02-27 15:22:53 +0000
committerVille Penttinen <[email protected]>2019-02-27 15:51:59 +0000
commitbb4521be1cbf10712804bb1e2dadbdfbf942437a (patch)
tree9c1ab5b302d6d95c772b827d5a491fa0e331df92
parent2e2a6dd2fbeb4da16e602fa1902ab6bbd850b442 (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.rs44
-rw-r--r--crates/ra_ide_api/src/marks.rs1
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);