generate Debug for enums

This commit is contained in:
Yoshua Wuyts 2021-08-08 15:24:04 +02:00
parent a1f2c7adcd
commit 4b7ae9fedc
2 changed files with 80 additions and 1 deletions

View file

@ -181,7 +181,37 @@ fn impl_def_from_trait(
fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn, annotated_name: &ast::Name) {
match adt {
ast::Adt::Union(_) => {} // `Debug` cannot be derived for unions, so no default impl can be provided.
ast::Adt::Enum(enum_) => {} // TODO
ast::Adt::Enum(enum_) => {
if let Some(list) = enum_.variant_list() {
let mut arms = vec![];
for variant in list.variants() {
let name = variant.name().unwrap();
// => Self::<Variant>
let first = make::ext::ident_path("Self");
let second = make::ext::ident_path(&format!("{}", name));
let pat = make::path_pat(make::path_concat(first, second));
// => write!(f, "<Variant>")
let target = make::expr_path(make::ext::ident_path("f").into());
let fmt_string = make::expr_literal(&(format!("\"{}\"", name))).into();
let args = make::arg_list(vec![target, fmt_string]);
let target = make::expr_path(make::ext::ident_path("write"));
let expr = make::expr_macro_call(target, args);
// => Self::<Variant> => write!(f, "<Variant>"),
arms.push(make::match_arm(Some(pat.into()), None, expr.into()));
}
// => match self { ... }
let f_path = make::expr_path(make::ext::ident_path("self"));
let list = make::match_arm_list(arms);
let expr = make::expr_match(f_path, list);
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
ted::replace(func.body().unwrap().syntax(), body.clone_for_update().syntax());
}
}
ast::Adt::Struct(strukt) => match strukt.field_list() {
Some(ast::FieldList::RecordFieldList(field_list)) => {
let name = format!("\"{}\"", annotated_name);
@ -383,6 +413,52 @@ impl fmt::Debug for Foo {
f.debug_struct("Foo").finish()
}
}
"#,
)
}
#[test]
fn add_custom_impl_debug_enum() {
check_assist(
replace_derive_with_manual_impl,
r#"
mod fmt {
pub struct Error;
pub type Result = Result<(), Error>;
pub struct Formatter<'a>;
pub trait Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
}
}
#[derive(Debu$0g)]
enum Foo {
Bar,
Baz,
}
"#,
r#"
mod fmt {
pub struct Error;
pub type Result = Result<(), Error>;
pub struct Formatter<'a>;
pub trait Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
}
}
enum Foo {
Bar,
Baz,
}
impl fmt::Debug for Foo {
$0fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Bar => write!(f, "Bar"),
Self::Baz => write!(f, "Baz"),
}
}
}
"#,
)
}

View file

@ -311,6 +311,9 @@ pub fn expr_method_call(
) -> ast::Expr {
expr_from_text(&format!("{}.{}{}", receiver, method, arg_list))
}
pub fn expr_macro_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr {
expr_from_text(&format!("{}!{}", f, arg_list))
}
pub fn expr_ref(expr: ast::Expr, exclusive: bool) -> ast::Expr {
expr_from_text(&if exclusive { format!("&mut {}", expr) } else { format!("&{}", expr) })
}