aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-06-14 20:07:07 +0100
committerLukas Wirth <[email protected]>2021-06-14 20:07:07 +0100
commit2c8e89b6f074d7ce44b6f649dbbd383a49f0f6c6 (patch)
tree507a63ae6b5f9682fcfc059e8bae95406332a9ba /crates/ide
parent401d79ac0674ec62689949c3a531836420cb9beb (diff)
Support goto type for field expressions and patterns
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/goto_type_definition.rs62
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#"
104struct Bar;
105 // ^^^
106struct Foo { foo: Bar }
107fn foo() {
108 Foo { foo$0 }
109}
110"#,
111 );
112 check(
113 r#"
114struct Bar;
115 // ^^^
116struct Foo { foo: Bar }
117fn 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#"
128struct Bar;
129 // ^^^
130struct Foo { foo: Bar }
131fn foo() {
132 let Foo { foo$0 };
133}
134"#,
135 );
136 check(
137 r#"
138struct Bar;
139 // ^^^
140struct Foo { foo: Bar }
141fn 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#"