This commit is contained in:
Yoshua Wuyts 2021-08-08 13:09:50 +02:00
parent f2e547d587
commit e2ab2e12a0
2 changed files with 34 additions and 17 deletions

View File

@ -35,8 +35,8 @@ use crate::{
// struct S; // struct S;
// //
// impl Debug for S { // impl Debug for S {
// fn fmt(&self, f: &mut Formatter) -> Result<()> { // $0fn fmt(&self, f: &mut Formatter) -> Result<()> {
// ${0:todo!()} // f.debug_struct(S)
// } // }
// } // }
// ``` // ```
@ -114,7 +114,7 @@ fn add_assist(
|builder| { |builder| {
let insert_pos = adt.syntax().text_range().end(); let insert_pos = adt.syntax().text_range().end();
let impl_def_with_items = 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); update_attribute(builder, input, &trait_name, attr);
let trait_path = format!("{}", trait_path); let trait_path = format!("{}", trait_path);
match (ctx.config.snippet_cap, impl_def_with_items) { match (ctx.config.snippet_cap, impl_def_with_items) {
@ -155,6 +155,7 @@ fn add_assist(
fn impl_def_from_trait( fn impl_def_from_trait(
sema: &hir::Semantics<ide_db::RootDatabase>, sema: &hir::Semantics<ide_db::RootDatabase>,
adt: &ast::Adt,
annotated_name: &ast::Name, annotated_name: &ast::Name,
trait_: Option<hir::Trait>, trait_: Option<hir::Trait>,
trait_path: &ast::Path, 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())); make::impl_trait(trait_path.clone(), make::ext::ident_path(&annotated_name.text()));
let (impl_def, first_assoc_item) = let (impl_def, first_assoc_item) =
add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope); add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope);
if let ast::AssocItem::Fn(fn_) = &first_assoc_item { if let ast::AssocItem::Fn(fn_) = &first_assoc_item {
if trait_path.segment().unwrap().name_ref().unwrap().text() == "Debug" { if trait_path.segment().unwrap().name_ref().unwrap().text() == "Debug" {
let f_expr = make::expr_path(make::ext::ident_path("f")); gen_debug_impl(adt, fn_, annotated_name);
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(),
);
} }
} }
Some((impl_def, first_assoc_item)) 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( fn update_attribute(
builder: &mut AssistBuilder, builder: &mut AssistBuilder,
input: &ast::TokenTree, input: &ast::TokenTree,

View File

@ -1363,8 +1363,8 @@ trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
struct S; struct S;
impl Debug for S { impl Debug for S {
fn fmt(&self, f: &mut Formatter) -> Result<()> { $0fn fmt(&self, f: &mut Formatter) -> Result<()> {
${0:todo!()} f.debug_struct(S)
} }
} }
"#####, "#####,