From e2ab2e12a0e1ce0836cd1cdebf6338580f2aca14 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Sun, 8 Aug 2021 13:09:50 +0200 Subject: [PATCH] wip --- .../replace_derive_with_manual_impl.rs | 47 +++++++++++++------ crates/ide_assists/src/tests/generated.rs | 4 +- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs index 761ccff8516..887fa34c781 100644 --- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs @@ -35,8 +35,8 @@ use crate::{ // struct S; // // impl Debug for S { -// fn fmt(&self, f: &mut Formatter) -> Result<()> { -// ${0:todo!()} +// $0fn fmt(&self, f: &mut Formatter) -> Result<()> { +// f.debug_struct(S) // } // } // ``` @@ -114,7 +114,7 @@ fn add_assist( |builder| { let insert_pos = adt.syntax().text_range().end(); let impl_def_with_items = - impl_def_from_trait(&ctx.sema, &annotated_name, trait_, trait_path); + impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, trait_path); update_attribute(builder, input, &trait_name, attr); let trait_path = format!("{}", trait_path); match (ctx.config.snippet_cap, impl_def_with_items) { @@ -155,6 +155,7 @@ fn add_assist( fn impl_def_from_trait( sema: &hir::Semantics, + adt: &ast::Adt, annotated_name: &ast::Name, trait_: Option, trait_path: &ast::Path, @@ -169,25 +170,41 @@ fn impl_def_from_trait( make::impl_trait(trait_path.clone(), make::ext::ident_path(&annotated_name.text())); let (impl_def, first_assoc_item) = add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope); + if let ast::AssocItem::Fn(fn_) = &first_assoc_item { if trait_path.segment().unwrap().name_ref().unwrap().text() == "Debug" { - let f_expr = make::expr_path(make::ext::ident_path("f")); - let args = make::arg_list(Some(make::expr_path(make::ext::ident_path( - annotated_name.text().as_str(), - )))); - let body = - make::block_expr(None, Some(make::expr_method_call(f_expr, "debug_struct", args))) - .indent(ast::edit::IndentLevel(1)); - - ted::replace( - fn_.body().unwrap().tail_expr().unwrap().syntax(), - body.clone_for_update().syntax(), - ); + gen_debug_impl(adt, fn_, annotated_name); } } Some((impl_def, first_assoc_item)) } +fn gen_debug_impl(adt: &ast::Adt, fn_: &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(_) => {} // TODO + ast::Adt::Struct(strukt) => { + match strukt.field_list() { + Some(ast::FieldList::RecordFieldList(field_list)) => { + let name = format!("\"{}\"", annotated_name); + let args = make::arg_list(Some(make::expr_literal(&name).into())); + let target = make::expr_path(make::ext::ident_path("f")); + let mut expr = make::expr_method_call(target, "debug_struct", args); + for field in field_list.fields() { + let args = make::arg_list(Some(make::expr_path(&name).into())); + expr = make::expr_method_call(expr, "field", args); + } + let expr = make::expr_method_call(expr, "finish", make::arg_list(None)); + let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1)); + ted::replace(fn_.body().unwrap().syntax(), body.clone_for_update().syntax()); + } + Some(ast::FieldList::TupleFieldList(field_list)) => {} + None => {} // `Debug` cannot be implemented for an incomplete struct. + } + } + } +} + fn update_attribute( builder: &mut AssistBuilder, input: &ast::TokenTree, diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs index ebf312aa3f8..54dde4767c3 100644 --- a/crates/ide_assists/src/tests/generated.rs +++ b/crates/ide_assists/src/tests/generated.rs @@ -1363,8 +1363,8 @@ trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; } struct S; impl Debug for S { - fn fmt(&self, f: &mut Formatter) -> Result<()> { - ${0:todo!()} + $0fn fmt(&self, f: &mut Formatter) -> Result<()> { + f.debug_struct(S) } } "#####,