Skip to content

Commit bae22f9

Browse files
Merge #9924
9924: Fix gen debug for enums r=yoshuawuyts a=yoshuawuyts Closes #9914. Thanks! r? `@Veykril` Co-authored-by: Yoshua Wuyts <yoshuawuyts@gmail.com>
2 parents 6a07bf6 + 067dc66 commit bae22f9

File tree

2 files changed

+148
-9
lines changed

2 files changed

+148
-9
lines changed

crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,71 @@ impl core::fmt::Debug for Foo {
302302
}
303303
}
304304
}
305+
"#,
306+
)
307+
}
308+
309+
#[test]
310+
fn add_custom_impl_debug_tuple_enum() {
311+
check_assist(
312+
replace_derive_with_manual_impl,
313+
r#"
314+
//- minicore: fmt
315+
#[derive(Debu$0g)]
316+
enum Foo {
317+
Bar(usize, usize),
318+
Baz,
319+
}
320+
"#,
321+
r#"
322+
enum Foo {
323+
Bar(usize, usize),
324+
Baz,
325+
}
326+
327+
impl core::fmt::Debug for Foo {
328+
$0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
329+
match self {
330+
Self::Bar(arg0, arg1) => f.debug_tuple("Bar").field(arg0).field(arg1).finish(),
331+
Self::Baz => write!(f, "Baz"),
332+
}
333+
}
334+
}
335+
"#,
336+
)
337+
}
338+
#[test]
339+
fn add_custom_impl_debug_record_enum() {
340+
check_assist(
341+
replace_derive_with_manual_impl,
342+
r#"
343+
//- minicore: fmt
344+
#[derive(Debu$0g)]
345+
enum Foo {
346+
Bar {
347+
baz: usize,
348+
qux: usize,
349+
},
350+
Baz,
351+
}
352+
"#,
353+
r#"
354+
enum Foo {
355+
Bar {
356+
baz: usize,
357+
qux: usize,
358+
},
359+
Baz,
360+
}
361+
362+
impl core::fmt::Debug for Foo {
363+
$0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
364+
match self {
365+
Self::Bar { baz, qux } => f.debug_struct("Bar").field("baz", baz).field("qux", qux).finish(),
366+
Self::Baz => write!(f, "Baz"),
367+
}
368+
}
369+
}
305370
"#,
306371
)
307372
}

crates/ide_assists/src/utils/gen_trait_fn_body.rs

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,90 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
149149
let mut arms = vec![];
150150
for variant in list.variants() {
151151
let name = variant.name()?;
152-
let variant_name =
153-
make::path_pat(make::ext::path_from_idents(["Self", &format!("{}", name)])?);
154-
152+
let variant_name = make::ext::path_from_idents(["Self", &format!("{}", name)])?;
155153
let target = make::expr_path(make::ext::ident_path("f").into());
156-
let fmt_string = make::expr_literal(&(format!("\"{}\"", name))).into();
157-
let args = make::arg_list(vec![target, fmt_string]);
158-
let macro_name = make::expr_path(make::ext::ident_path("write"));
159-
let macro_call = make::expr_macro_call(macro_name, args);
160154

161-
arms.push(make::match_arm(Some(variant_name.into()), None, macro_call.into()));
155+
match variant.field_list() {
156+
Some(ast::FieldList::RecordFieldList(list)) => {
157+
// => f.debug_struct(name)
158+
let target = make::expr_path(make::ext::ident_path("f"));
159+
let method = make::name_ref("debug_struct");
160+
let struct_name = format!("\"{}\"", name);
161+
let args = make::arg_list(Some(make::expr_literal(&struct_name).into()));
162+
let mut expr = make::expr_method_call(target, method, args);
163+
164+
let mut pats = vec![];
165+
for field in list.fields() {
166+
let field_name = field.name()?;
167+
168+
// create a field pattern for use in `MyStruct { fields.. }`
169+
let pat = make::ident_pat(false, false, field_name.clone());
170+
pats.push(pat.into());
171+
172+
// => <expr>.field("field_name", field)
173+
let method_name = make::name_ref("field");
174+
let name = make::expr_literal(&(format!("\"{}\"", field_name))).into();
175+
let path = &format!("{}", field_name);
176+
let path = make::expr_path(make::ext::ident_path(path));
177+
let args = make::arg_list(vec![name, path]);
178+
expr = make::expr_method_call(expr, method_name, args);
179+
}
180+
181+
// => <expr>.finish()
182+
let method = make::name_ref("finish");
183+
let expr = make::expr_method_call(expr, method, make::arg_list(None));
184+
185+
// => MyStruct { fields.. } => f.debug_struct("MyStruct")...finish(),
186+
let pat = make::record_pat(variant_name.clone(), pats.into_iter());
187+
arms.push(make::match_arm(Some(pat.into()), None, expr));
188+
}
189+
Some(ast::FieldList::TupleFieldList(list)) => {
190+
// => f.debug_tuple(name)
191+
let target = make::expr_path(make::ext::ident_path("f"));
192+
let method = make::name_ref("debug_tuple");
193+
let struct_name = format!("\"{}\"", name);
194+
let args = make::arg_list(Some(make::expr_literal(&struct_name).into()));
195+
let mut expr = make::expr_method_call(target, method, args);
196+
197+
let mut pats = vec![];
198+
for (i, _) in list.fields().enumerate() {
199+
let name = format!("arg{}", i);
200+
201+
// create a field pattern for use in `MyStruct(fields..)`
202+
let field_name = make::name(&name);
203+
let pat = make::ident_pat(false, false, field_name.clone());
204+
pats.push(pat.into());
205+
206+
// => <expr>.field(field)
207+
let method_name = make::name_ref("field");
208+
let field_path = &format!("{}", name);
209+
let field_path = make::expr_path(make::ext::ident_path(field_path));
210+
let args = make::arg_list(vec![field_path]);
211+
expr = make::expr_method_call(expr, method_name, args);
212+
}
213+
214+
// => <expr>.finish()
215+
let method = make::name_ref("finish");
216+
let expr = make::expr_method_call(expr, method, make::arg_list(None));
217+
218+
// => MyStruct (fields..) => f.debug_tuple("MyStruct")...finish(),
219+
let pat = make::tuple_struct_pat(variant_name.clone(), pats.into_iter());
220+
arms.push(make::match_arm(Some(pat.into()), None, expr));
221+
}
222+
None => {
223+
let fmt_string = make::expr_literal(&(format!("\"{}\"", name))).into();
224+
let args = make::arg_list([target, fmt_string]);
225+
let macro_name = make::expr_path(make::ext::ident_path("write"));
226+
let macro_call = make::expr_macro_call(macro_name, args);
227+
228+
let variant_name = make::path_pat(variant_name);
229+
arms.push(make::match_arm(
230+
Some(variant_name.into()),
231+
None,
232+
macro_call.into(),
233+
));
234+
}
235+
}
162236
}
163237

164238
let match_target = make::expr_path(make::ext::ident_path("self"));
@@ -190,7 +264,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
190264
let f_path = make::expr_path(make::ext::ident_path("self"));
191265
let f_path = make::expr_ref(f_path, false);
192266
let f_path = make::expr_field(f_path, &format!("{}", name)).into();
193-
let args = make::arg_list(vec![f_name, f_path]);
267+
let args = make::arg_list([f_name, f_path]);
194268
expr = make::expr_method_call(expr, make::name_ref("field"), args);
195269
}
196270
expr

0 commit comments

Comments
 (0)