Skip to content

Commit e0adb39

Browse files
committed
gen clone for record enums
1 parent 7ddc26a commit e0adb39

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,40 @@ impl Clone for Foo {
572572
}
573573
}
574574
}
575+
"#,
576+
)
577+
}
578+
579+
#[test]
580+
fn add_custom_impl_clone_record_enum() {
581+
check_assist(
582+
replace_derive_with_manual_impl,
583+
r#"
584+
//- minicore: clone
585+
#[derive(Clo$0ne)]
586+
enum Foo {
587+
Bar {
588+
bin: String,
589+
},
590+
Baz,
591+
}
592+
"#,
593+
r#"
594+
enum Foo {
595+
Bar {
596+
bin: String,
597+
},
598+
Baz,
599+
}
600+
601+
impl Clone for Foo {
602+
$0fn clone(&self) -> Self {
603+
match self {
604+
Self::Bar { bin } => Self::Bar { bin: bin.clone() },
605+
Self::Baz => Self::Baz,
606+
}
607+
}
608+
}
575609
"#,
576610
)
577611
}

crates/ide_assists/src/utils/gen_trait_fn_body.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,40 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
4242
let right = make::ext::ident_path(&format!("{}", name));
4343
let variant_name = make::path_concat(left, right);
4444

45-
let pattern = make::path_pat(variant_name.clone());
46-
let variant_expr = make::expr_path(variant_name);
47-
arms.push(make::match_arm(Some(pattern.into()), None, variant_expr));
45+
match variant.field_list() {
46+
// => match self { Self::Name { x } => Self::Name { x: x.clone() } }
47+
Some(ast::FieldList::RecordFieldList(list)) => {
48+
let mut pats = vec![];
49+
let mut fields = vec![];
50+
for field in list.fields() {
51+
let field_name = field.name()?;
52+
let pat = make::ident_pat(false, false, field_name.clone());
53+
pats.push(pat.into());
54+
55+
let path = make::ext::ident_path(&field_name.to_string());
56+
let method_call = gen_clone_call(make::expr_path(path));
57+
let name_ref = make::name_ref(&field_name.to_string());
58+
let field = make::record_expr_field(name_ref, Some(method_call));
59+
fields.push(field);
60+
}
61+
let pattern = make::record_pat(variant_name.clone(), pats.into_iter());
62+
63+
let fields = make::record_expr_field_list(fields);
64+
let record_expr = make::record_expr(variant_name, fields).into();
65+
66+
arms.push(make::match_arm(Some(pattern.into()), None, record_expr));
67+
}
68+
69+
// => match self { Self::Name(arg1) => Self::Name(arg1.clone()) }
70+
Some(ast::FieldList::TupleFieldList(list)) => todo!(),
71+
72+
// => match self { Self::Name => Self::Name }
73+
None => {
74+
let pattern = make::path_pat(variant_name.clone());
75+
let variant_expr = make::expr_path(variant_name);
76+
arms.push(make::match_arm(Some(pattern.into()), None, variant_expr));
77+
}
78+
}
4879
}
4980

5081
let match_target = make::expr_path(make::ext::ident_path("self"));

0 commit comments

Comments
 (0)