diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ide/src/goto_type_definition.rs | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs index 004d9cb68..ca3c02bf6 100644 --- a/crates/ide/src/goto_type_definition.rs +++ b/crates/ide/src/goto_type_definition.rs | |||
@@ -25,7 +25,7 @@ pub(crate) fn goto_type_definition( | |||
25 | let token: SyntaxToken = pick_best(file.syntax().token_at_offset(position.offset))?; | 25 | let token: SyntaxToken = pick_best(file.syntax().token_at_offset(position.offset))?; |
26 | let token: SyntaxToken = sema.descend_into_macros(token); | 26 | let token: SyntaxToken = sema.descend_into_macros(token); |
27 | 27 | ||
28 | let (ty, node) = sema.token_ancestors_with_macros(token).find_map(|node| { | 28 | let (ty, node) = sema.token_ancestors_with_macros(token.clone()).find_map(|node| { |
29 | let ty = match_ast! { | 29 | let ty = match_ast! { |
30 | match node { | 30 | match node { |
31 | ast::Expr(it) => sema.type_of_expr(&it)?, | 31 | ast::Expr(it) => sema.type_of_expr(&it)?, |
@@ -33,13 +33,23 @@ pub(crate) fn goto_type_definition( | |||
33 | ast::SelfParam(it) => sema.type_of_self(&it)?, | 33 | ast::SelfParam(it) => sema.type_of_self(&it)?, |
34 | ast::Type(it) => sema.resolve_type(&it)?, | 34 | ast::Type(it) => sema.resolve_type(&it)?, |
35 | ast::RecordField(it) => sema.to_def(&it).map(|d| d.ty(db.upcast()))?, | 35 | ast::RecordField(it) => sema.to_def(&it).map(|d| d.ty(db.upcast()))?, |
36 | ast::RecordField(it) => sema.to_def(&it).map(|d| d.ty(db.upcast()))?, | ||
37 | // can't match on RecordExprField directly as `ast::Expr` will match an iteration too early otherwise | ||
38 | ast::NameRef(it) => { | ||
39 | if let Some(record_field) = ast::RecordExprField::for_name_ref(&it) { | ||
40 | let (_, _, ty) = sema.resolve_record_field(&record_field)?; | ||
41 | ty | ||
42 | } else { | ||
43 | let record_field = ast::RecordPatField::for_field_name_ref(&it)?; | ||
44 | sema.resolve_record_pat_field(&record_field)?.ty(db) | ||
45 | } | ||
46 | }, | ||
36 | _ => return None, | 47 | _ => return None, |
37 | } | 48 | } |
38 | }; | 49 | }; |
39 | 50 | ||
40 | Some((ty, node)) | 51 | Some((ty, node)) |
41 | })?; | 52 | })?; |
42 | |||
43 | let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; | 53 | let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; |
44 | 54 | ||
45 | let nav = adt_def.try_to_nav(db)?; | 55 | let nav = adt_def.try_to_nav(db)?; |
@@ -88,6 +98,54 @@ fn foo() { | |||
88 | } | 98 | } |
89 | 99 | ||
90 | #[test] | 100 | #[test] |
101 | fn goto_type_definition_record_expr_field() { | ||
102 | check( | ||
103 | r#" | ||
104 | struct Bar; | ||
105 | // ^^^ | ||
106 | struct Foo { foo: Bar } | ||
107 | fn foo() { | ||
108 | Foo { foo$0 } | ||
109 | } | ||
110 | "#, | ||
111 | ); | ||
112 | check( | ||
113 | r#" | ||
114 | struct Bar; | ||
115 | // ^^^ | ||
116 | struct Foo { foo: Bar } | ||
117 | fn foo() { | ||
118 | Foo { foo$0: Bar } | ||
119 | } | ||
120 | "#, | ||
121 | ); | ||
122 | } | ||
123 | |||
124 | #[test] | ||
125 | fn goto_type_definition_record_pat_field() { | ||
126 | check( | ||
127 | r#" | ||
128 | struct Bar; | ||
129 | // ^^^ | ||
130 | struct Foo { foo: Bar } | ||
131 | fn foo() { | ||
132 | let Foo { foo$0 }; | ||
133 | } | ||
134 | "#, | ||
135 | ); | ||
136 | check( | ||
137 | r#" | ||
138 | struct Bar; | ||
139 | // ^^^ | ||
140 | struct Foo { foo: Bar } | ||
141 | fn foo() { | ||
142 | let Foo { foo$0: bar }; | ||
143 | } | ||
144 | "#, | ||
145 | ); | ||
146 | } | ||
147 | |||
148 | #[test] | ||
91 | fn goto_type_definition_works_simple_ref() { | 149 | fn goto_type_definition_works_simple_ref() { |
92 | check( | 150 | check( |
93 | r#" | 151 | r#" |