diff options
-rw-r--r-- | crates/ra_assists/src/fill_struct_fields.rs | 58 |
1 files changed, 45 insertions, 13 deletions
diff --git a/crates/ra_assists/src/fill_struct_fields.rs b/crates/ra_assists/src/fill_struct_fields.rs index 938322d1d..90ce9c577 100644 --- a/crates/ra_assists/src/fill_struct_fields.rs +++ b/crates/ra_assists/src/fill_struct_fields.rs | |||
@@ -3,39 +3,34 @@ use std::fmt::Write; | |||
3 | use hir::{AdtDef, Ty, source_binder}; | 3 | use hir::{AdtDef, Ty, source_binder}; |
4 | use hir::db::HirDatabase; | 4 | use hir::db::HirDatabase; |
5 | 5 | ||
6 | use ra_syntax::ast::{self, AstNode, Expr}; | 6 | use ra_syntax::ast::{self, AstNode}; |
7 | 7 | ||
8 | use crate::{AssistCtx, Assist, AssistId}; | 8 | use crate::{AssistCtx, Assist, AssistId}; |
9 | 9 | ||
10 | pub(crate) fn fill_struct_fields(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 10 | pub(crate) fn fill_struct_fields(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
11 | let struct_lit = ctx.node_at_offset::<ast::StructLit>()?; | 11 | let struct_lit = ctx.node_at_offset::<ast::StructLit>()?; |
12 | let named_field_list = struct_lit.named_field_list()?; | ||
12 | 13 | ||
13 | // If we already have existing struct fields, don't provide the assist. | 14 | // If we already have existing struct fields, don't provide the assist. |
14 | match struct_lit.named_field_list() { | 15 | if named_field_list.fields().count() > 0 { |
15 | Some(named_field_list) if named_field_list.fields().count() > 0 => { | 16 | return None; |
16 | return None; | ||
17 | } | ||
18 | _ => {} | ||
19 | } | 17 | } |
20 | 18 | ||
21 | let expr: &Expr = struct_lit.into(); | ||
22 | let function = | 19 | let function = |
23 | source_binder::function_from_child_node(ctx.db, ctx.frange.file_id, struct_lit.syntax())?; | 20 | source_binder::function_from_child_node(ctx.db, ctx.frange.file_id, struct_lit.syntax())?; |
24 | 21 | ||
25 | let infer_result = function.infer(ctx.db); | 22 | let infer_result = function.infer(ctx.db); |
26 | let source_map = function.body_source_map(ctx.db); | 23 | let source_map = function.body_source_map(ctx.db); |
27 | let node_expr = source_map.node_expr(expr)?; | 24 | let node_expr = source_map.node_expr(struct_lit.into())?; |
28 | let struct_lit_ty = infer_result[node_expr].clone(); | 25 | let struct_lit_ty = infer_result[node_expr].clone(); |
29 | let struct_def = match struct_lit_ty { | 26 | let struct_def = match struct_lit_ty { |
30 | Ty::Adt { def_id: AdtDef::Struct(s), .. } => s, | 27 | Ty::Adt { def_id: AdtDef::Struct(s), .. } => s, |
31 | _ => return None, | 28 | _ => return None, |
32 | }; | 29 | }; |
33 | 30 | ||
34 | let struct_name = struct_def.name(ctx.db)?; | ||
35 | let db = ctx.db; | 31 | let db = ctx.db; |
36 | |||
37 | ctx.add_action(AssistId("fill_struct_fields"), "fill struct fields", |edit| { | 32 | ctx.add_action(AssistId("fill_struct_fields"), "fill struct fields", |edit| { |
38 | let mut buf = format!("{} {{\n", struct_name); | 33 | let mut buf = String::from("{\n"); |
39 | let struct_fields = struct_def.fields(db); | 34 | let struct_fields = struct_def.fields(db); |
40 | for field in struct_fields { | 35 | for field in struct_fields { |
41 | let field_name = field.name(db).to_string(); | 36 | let field_name = field.name(db).to_string(); |
@@ -44,8 +39,8 @@ pub(crate) fn fill_struct_fields(mut ctx: AssistCtx<impl HirDatabase>) -> Option | |||
44 | buf.push_str("}"); | 39 | buf.push_str("}"); |
45 | 40 | ||
46 | edit.target(struct_lit.syntax().range()); | 41 | edit.target(struct_lit.syntax().range()); |
47 | edit.set_cursor(expr.syntax().range().start()); | 42 | edit.set_cursor(struct_lit.syntax().range().start()); |
48 | edit.replace_node_and_indent(struct_lit.syntax(), buf); | 43 | edit.replace_node_and_indent(named_field_list.syntax(), buf); |
49 | }); | 44 | }); |
50 | 45 | ||
51 | ctx.build() | 46 | ctx.build() |
@@ -116,4 +111,41 @@ mod tests { | |||
116 | "S {}", | 111 | "S {}", |
117 | ); | 112 | ); |
118 | } | 113 | } |
114 | |||
115 | #[test] | ||
116 | fn fill_struct_fields_preserve_self() { | ||
117 | check_assist( | ||
118 | fill_struct_fields, | ||
119 | r#" | ||
120 | struct Foo { | ||
121 | foo: u8, | ||
122 | bar: String, | ||
123 | baz: i128, | ||
124 | } | ||
125 | |||
126 | impl Foo { | ||
127 | pub fn new() -> Self { | ||
128 | Self <|>{} | ||
129 | } | ||
130 | } | ||
131 | "#, | ||
132 | r#" | ||
133 | struct Foo { | ||
134 | foo: u8, | ||
135 | bar: String, | ||
136 | baz: i128, | ||
137 | } | ||
138 | |||
139 | impl Foo { | ||
140 | pub fn new() -> Self { | ||
141 | <|>Self { | ||
142 | foo: (), | ||
143 | bar: (), | ||
144 | baz: (), | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | "#, | ||
149 | ); | ||
150 | } | ||
119 | } | 151 | } |