diff options
Diffstat (limited to 'crates/ra_assists')
-rw-r--r-- | crates/ra_assists/src/fill_struct_fields.rs | 120 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 2 |
2 files changed, 122 insertions, 0 deletions
diff --git a/crates/ra_assists/src/fill_struct_fields.rs b/crates/ra_assists/src/fill_struct_fields.rs new file mode 100644 index 000000000..05a5ebf66 --- /dev/null +++ b/crates/ra_assists/src/fill_struct_fields.rs | |||
@@ -0,0 +1,120 @@ | |||
1 | use std::fmt::Write; | ||
2 | |||
3 | use hir::{AdtDef, Ty, source_binder}; | ||
4 | use hir::db::HirDatabase; | ||
5 | |||
6 | use ra_syntax::ast::{self, AstNode, Expr}; | ||
7 | |||
8 | use crate::{AssistCtx, Assist, AssistId}; | ||
9 | |||
10 | pub(crate) fn fill_struct_fields(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | ||
11 | let struct_lit = ctx.node_at_offset::<ast::StructLit>()?; | ||
12 | |||
13 | // If we already have existing struct fields, don't provide the assist. | ||
14 | // TODO: provide assist for tuple structs | ||
15 | match struct_lit.named_field_list() { | ||
16 | Some(named_field_list) if named_field_list.fields().count() > 0 => { | ||
17 | return None; | ||
18 | } | ||
19 | _ => {} | ||
20 | } | ||
21 | |||
22 | let expr: &Expr = struct_lit.into(); | ||
23 | let function = | ||
24 | source_binder::function_from_child_node(ctx.db, ctx.frange.file_id, struct_lit.syntax())?; | ||
25 | |||
26 | let infer_result = function.infer(ctx.db); | ||
27 | let source_map = function.body_source_map(ctx.db); | ||
28 | let node_expr = source_map.node_expr(expr)?; | ||
29 | let struct_lit_ty = infer_result[node_expr].clone(); | ||
30 | let struct_def = match struct_lit_ty { | ||
31 | Ty::Adt { def_id: AdtDef::Struct(s), .. } => s, | ||
32 | _ => return None, | ||
33 | }; | ||
34 | |||
35 | let struct_name = struct_def.name(ctx.db)?; | ||
36 | let db = ctx.db; | ||
37 | |||
38 | ctx.add_action(AssistId("fill_struct_fields"), "fill struct fields", |edit| { | ||
39 | let mut buf = format!("{} {{\n", struct_name); | ||
40 | let struct_fields = struct_def.fields(db); | ||
41 | for field in struct_fields { | ||
42 | let field_name = field.name(db).to_string(); | ||
43 | write!(&mut buf, " {}: (),\n", field_name).unwrap(); | ||
44 | } | ||
45 | buf.push_str("}"); | ||
46 | |||
47 | edit.target(struct_lit.syntax().range()); | ||
48 | edit.set_cursor(expr.syntax().range().start()); | ||
49 | edit.replace_node_and_indent(struct_lit.syntax(), buf); | ||
50 | }); | ||
51 | |||
52 | ctx.build() | ||
53 | } | ||
54 | |||
55 | #[cfg(test)] | ||
56 | mod tests { | ||
57 | use crate::helpers::{check_assist, check_assist_target}; | ||
58 | |||
59 | use super::fill_struct_fields; | ||
60 | |||
61 | #[test] | ||
62 | fn fill_struct_fields_empty_body() { | ||
63 | check_assist( | ||
64 | fill_struct_fields, | ||
65 | r#" | ||
66 | struct S<'a, D> { | ||
67 | a: u32, | ||
68 | b: String, | ||
69 | c: (i32, i32), | ||
70 | d: D, | ||
71 | r: &'a str, | ||
72 | } | ||
73 | |||
74 | fn main() { | ||
75 | let s = S<|> {} | ||
76 | } | ||
77 | "#, | ||
78 | r#" | ||
79 | struct S<'a, D> { | ||
80 | a: u32, | ||
81 | b: String, | ||
82 | c: (i32, i32), | ||
83 | d: D, | ||
84 | r: &'a str, | ||
85 | } | ||
86 | |||
87 | fn main() { | ||
88 | let s = <|>S { | ||
89 | a: (), | ||
90 | b: (), | ||
91 | c: (), | ||
92 | d: (), | ||
93 | r: (), | ||
94 | } | ||
95 | } | ||
96 | "#, | ||
97 | ); | ||
98 | } | ||
99 | |||
100 | #[test] | ||
101 | fn fill_struct_fields_target() { | ||
102 | check_assist_target( | ||
103 | fill_struct_fields, | ||
104 | r#" | ||
105 | struct S<'a, D> { | ||
106 | a: u32, | ||
107 | b: String, | ||
108 | c: (i32, i32), | ||
109 | d: D, | ||
110 | r: &'a str, | ||
111 | } | ||
112 | |||
113 | fn main() { | ||
114 | let s = S<|> {} | ||
115 | } | ||
116 | "#, | ||
117 | "S {}", | ||
118 | ); | ||
119 | } | ||
120 | } | ||
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 6c3d75d79..5efc5025e 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -90,6 +90,7 @@ mod add_impl; | |||
90 | mod flip_comma; | 90 | mod flip_comma; |
91 | mod change_visibility; | 91 | mod change_visibility; |
92 | mod fill_match_arms; | 92 | mod fill_match_arms; |
93 | mod fill_struct_fields; | ||
93 | mod introduce_variable; | 94 | mod introduce_variable; |
94 | mod replace_if_let_with_match; | 95 | mod replace_if_let_with_match; |
95 | mod split_import; | 96 | mod split_import; |
@@ -102,6 +103,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis | |||
102 | add_impl::add_impl, | 103 | add_impl::add_impl, |
103 | change_visibility::change_visibility, | 104 | change_visibility::change_visibility, |
104 | fill_match_arms::fill_match_arms, | 105 | fill_match_arms::fill_match_arms, |
106 | fill_struct_fields::fill_struct_fields, | ||
105 | flip_comma::flip_comma, | 107 | flip_comma::flip_comma, |
106 | introduce_variable::introduce_variable, | 108 | introduce_variable::introduce_variable, |
107 | replace_if_let_with_match::replace_if_let_with_match, | 109 | replace_if_let_with_match::replace_if_let_with_match, |