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 887fa34c781..8b82cbf5e05 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 @@ -36,7 +36,7 @@ use crate::{ // // impl Debug for S { // $0fn fmt(&self, f: &mut Formatter) -> Result<()> { -// f.debug_struct(S) +// f.debug_struct("S").finish() // } // } // ``` @@ -183,25 +183,37 @@ 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())); + 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() { + if let Some(name) = field.name() { + let f_name = make::expr_literal(&(format!("\"{}\"", name))).into(); + let f_path = make::expr_path(make::ext::ident_path("self")); + let f_path = make::expr_ref(f_path, false); + let f_path = make::expr_field(f_path, &format!("{}", name)).into(); + let args = make::arg_list(vec![f_name, f_path]); 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. + 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 => { + 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 expr = make::expr_method_call(target, "debug_struct", 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()); + } + }, } } diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs index 54dde4767c3..195f958208e 100644 --- a/crates/ide_assists/src/tests/generated.rs +++ b/crates/ide_assists/src/tests/generated.rs @@ -1364,7 +1364,7 @@ struct S; impl Debug for S { $0fn fmt(&self, f: &mut Formatter) -> Result<()> { - f.debug_struct(S) + f.debug_struct("S").finish() } } "#####, diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index e5fff983d0c..71254f08543 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -318,6 +318,9 @@ pub fn expr_closure(pats: impl IntoIterator, expr: ast::Expr) let params = pats.into_iter().join(", "); expr_from_text(&format!("|{}| {}", params, expr)) } +pub fn expr_field(receiver: ast::Expr, field: &str) -> ast::Expr { + expr_from_text(&format!("{}.{}", receiver, field)) +} pub fn expr_paren(expr: ast::Expr) -> ast::Expr { expr_from_text(&format!("({})", expr)) }