Skip to content

Commit 4b7ae9f

Browse files
committed
generate Debug for enums
1 parent a1f2c7a commit 4b7ae9f

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,37 @@ fn impl_def_from_trait(
181181
fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn, annotated_name: &ast::Name) {
182182
match adt {
183183
ast::Adt::Union(_) => {} // `Debug` cannot be derived for unions, so no default impl can be provided.
184-
ast::Adt::Enum(enum_) => {} // TODO
184+
ast::Adt::Enum(enum_) => {
185+
if let Some(list) = enum_.variant_list() {
186+
let mut arms = vec![];
187+
for variant in list.variants() {
188+
let name = variant.name().unwrap();
189+
190+
// => Self::<Variant>
191+
let first = make::ext::ident_path("Self");
192+
let second = make::ext::ident_path(&format!("{}", name));
193+
let pat = make::path_pat(make::path_concat(first, second));
194+
195+
// => write!(f, "<Variant>")
196+
let target = make::expr_path(make::ext::ident_path("f").into());
197+
let fmt_string = make::expr_literal(&(format!("\"{}\"", name))).into();
198+
let args = make::arg_list(vec![target, fmt_string]);
199+
let target = make::expr_path(make::ext::ident_path("write"));
200+
let expr = make::expr_macro_call(target, args);
201+
202+
// => Self::<Variant> => write!(f, "<Variant>"),
203+
arms.push(make::match_arm(Some(pat.into()), None, expr.into()));
204+
}
205+
206+
// => match self { ... }
207+
let f_path = make::expr_path(make::ext::ident_path("self"));
208+
let list = make::match_arm_list(arms);
209+
let expr = make::expr_match(f_path, list);
210+
211+
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
212+
ted::replace(func.body().unwrap().syntax(), body.clone_for_update().syntax());
213+
}
214+
}
185215
ast::Adt::Struct(strukt) => match strukt.field_list() {
186216
Some(ast::FieldList::RecordFieldList(field_list)) => {
187217
let name = format!("\"{}\"", annotated_name);
@@ -383,6 +413,52 @@ impl fmt::Debug for Foo {
383413
f.debug_struct("Foo").finish()
384414
}
385415
}
416+
"#,
417+
)
418+
}
419+
#[test]
420+
fn add_custom_impl_debug_enum() {
421+
check_assist(
422+
replace_derive_with_manual_impl,
423+
r#"
424+
mod fmt {
425+
pub struct Error;
426+
pub type Result = Result<(), Error>;
427+
pub struct Formatter<'a>;
428+
pub trait Debug {
429+
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
430+
}
431+
}
432+
433+
#[derive(Debu$0g)]
434+
enum Foo {
435+
Bar,
436+
Baz,
437+
}
438+
"#,
439+
r#"
440+
mod fmt {
441+
pub struct Error;
442+
pub type Result = Result<(), Error>;
443+
pub struct Formatter<'a>;
444+
pub trait Debug {
445+
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
446+
}
447+
}
448+
449+
enum Foo {
450+
Bar,
451+
Baz,
452+
}
453+
454+
impl fmt::Debug for Foo {
455+
$0fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456+
match self {
457+
Self::Bar => write!(f, "Bar"),
458+
Self::Baz => write!(f, "Baz"),
459+
}
460+
}
461+
}
386462
"#,
387463
)
388464
}

crates/syntax/src/ast/make.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,9 @@ pub fn expr_method_call(
311311
) -> ast::Expr {
312312
expr_from_text(&format!("{}.{}{}", receiver, method, arg_list))
313313
}
314+
pub fn expr_macro_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr {
315+
expr_from_text(&format!("{}!{}", f, arg_list))
316+
}
314317
pub fn expr_ref(expr: ast::Expr, exclusive: bool) -> ast::Expr {
315318
expr_from_text(&if exclusive { format!("&mut {}", expr) } else { format!("&{}", expr) })
316319
}

0 commit comments

Comments
 (0)