aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists')
-rw-r--r--crates/ra_assists/src/fill_struct_fields.rs120
-rw-r--r--crates/ra_assists/src/lib.rs2
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 @@
1use std::fmt::Write;
2
3use hir::{AdtDef, Ty, source_binder};
4use hir::db::HirDatabase;
5
6use ra_syntax::ast::{self, AstNode, Expr};
7
8use crate::{AssistCtx, Assist, AssistId};
9
10pub(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)]
56mod 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;
90mod flip_comma; 90mod flip_comma;
91mod change_visibility; 91mod change_visibility;
92mod fill_match_arms; 92mod fill_match_arms;
93mod fill_struct_fields;
93mod introduce_variable; 94mod introduce_variable;
94mod replace_if_let_with_match; 95mod replace_if_let_with_match;
95mod split_import; 96mod 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,