Skip to content

Commit b67378f

Browse files
committed
fix debug record structs
1 parent b641a66 commit b67378f

File tree

2 files changed

+117
-8
lines changed

2 files changed

+117
-8
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(arg1, arg2) => f.debug_tuple("Bar").field(arg1).field(arg2).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: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,60 @@ 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+
let mut pats = vec![];
158+
159+
// => f.debug_struct(name)
160+
let target = make::expr_path(make::ext::ident_path("f"));
161+
let method = make::name_ref("debug_struct");
162+
let struct_name = format!("\"{}\"", name);
163+
let args = make::arg_list(Some(make::expr_literal(&struct_name).into()));
164+
let mut expr = make::expr_method_call(target, method, args);
165+
166+
for field in list.fields() {
167+
let name = field.name()?;
168+
169+
// => MyStruct { field_name }
170+
let field_name = field.name()?;
171+
let pat = make::ident_pat(false, false, field_name.clone());
172+
pats.push(pat.into());
173+
174+
// => <expr>.field("field_name", field)
175+
let method_name = make::name_ref("field");
176+
let field_name = make::expr_literal(&(format!("\"{}\"", name))).into();
177+
let field_path = &format!("{}", name);
178+
let field_path = make::expr_path(make::ext::ident_path(field_path));
179+
let args = make::arg_list(vec![field_name, field_path]);
180+
expr = make::expr_method_call(expr, method_name, args);
181+
}
182+
183+
// => <expr>.finish()
184+
let method = make::name_ref("finish");
185+
let expr = make::expr_method_call(expr, method, make::arg_list(None));
186+
187+
// => MyStruct { fields.. } => f.debug_struct()...finish(),
188+
let pat = make::record_pat(variant_name.clone(), pats.into_iter());
189+
arms.push(make::match_arm(Some(pat.into()), None, expr));
190+
}
191+
Some(ast::FieldList::TupleFieldList(_list)) => todo!(),
192+
None => {
193+
let fmt_string = make::expr_literal(&(format!("\"{}\"", name))).into();
194+
let args = make::arg_list(vec![target, fmt_string]);
195+
let macro_name = make::expr_path(make::ext::ident_path("write"));
196+
let macro_call = make::expr_macro_call(macro_name, args);
197+
198+
let variant_name = make::path_pat(variant_name);
199+
arms.push(make::match_arm(
200+
Some(variant_name.into()),
201+
None,
202+
macro_call.into(),
203+
));
204+
}
205+
}
162206
}
163207

164208
let match_target = make::expr_path(make::ext::ident_path("self"));

0 commit comments

Comments
 (0)