use ide_db::helpers::{import_assets::NameToImport, mod_path_to_ast};
use ide_db::items_locator;
use itertools::Itertools;
-use syntax::ast::edit::AstNodeEdit;
-use syntax::ted;
use syntax::{
- ast::{self, make, AstNode, NameOwner},
+ ast::{self, make, AstNode, HasName},
SyntaxKind::{IDENT, WHITESPACE},
};
use crate::{
assist_context::{AssistBuilder, AssistContext, Assists},
utils::{
- add_trait_assoc_items_to_impl, filter_assoc_items, generate_trait_impl_text,
- render_snippet, Cursor, DefaultMethods,
+ add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body,
+ generate_trait_impl_text, render_snippet, Cursor, DefaultMethods,
},
AssistId, AssistKind,
};
add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope);
// Generate a default `impl` function body for the derived trait.
- if let ast::AssocItem::Fn(func) = &first_assoc_item {
- match trait_path.segment().unwrap().name_ref().unwrap().text().as_str() {
- "Debug" => gen_debug_impl(adt, func, annotated_name),
- _ => {}
- };
- }
- Some((impl_def, first_assoc_item))
-}
-
-/// Generate a `Debug` impl based on the fields and members of the target type.
-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_) => {
- // => match self { Self::Variant => write!(f, "Variant") }
- if let Some(list) = enum_.variant_list() {
- let mut arms = vec![];
- for variant in list.variants() {
- let name = variant.name().unwrap();
-
- let left = make::ext::ident_path("Self");
- let right = make::ext::ident_path(&format!("{}", name));
- let variant_name = make::path_pat(make::path_concat(left, right));
-
- 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 macro_name = make::expr_path(make::ext::ident_path("write"));
- let macro_call = make::expr_macro_call(macro_name, args);
-
- arms.push(make::match_arm(Some(variant_name.into()), None, macro_call.into()));
- }
-
- let match_target = make::expr_path(make::ext::ident_path("self"));
- let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1));
- let match_expr = make::expr_match(match_target, list);
-
- let body = make::block_expr(None, Some(match_expr));
- let body = body.indent(ast::edit::IndentLevel(1));
- ted::replace(func.body().unwrap().syntax(), body.clone_for_update().syntax());
- }
- }
- ast::Adt::Struct(strukt) => {
- 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 = match strukt.field_list() {
- None => {
- // => f.debug_struct("Name").finish()
- make::expr_method_call(target, "debug_struct", args)
- }
- Some(ast::FieldList::RecordFieldList(field_list)) => {
- // => f.debug_struct("Name").field("foo", &self.foo).finish()
- 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);
- }
- }
- expr
- }
- Some(ast::FieldList::TupleFieldList(field_list)) => {
- // => f.debug_tuple("Name").field(self.0).finish()
- let mut expr = make::expr_method_call(target, "debug_tuple", args);
- for (idx, _) in field_list.fields().enumerate() {
- 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!("{}", idx)).into();
- expr = make::expr_method_call(expr, "field", make::arg_list(Some(f_path)));
- }
- expr
- }
- };
+ if let ast::AssocItem::Fn(ref func) = first_assoc_item {
+ let _ = gen_trait_fn_body(func, trait_path, adt);
+ };
- 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(func.body().unwrap().syntax(), body.clone_for_update().syntax());
- }
- }
+ Some((impl_def, first_assoc_item))
}
fn update_attribute(
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;
- }
-}
-
+//- minicore: fmt
#[derive(Debu$0g)]
struct Foo {
bar: String,
}
"#,
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;
- }
-}
-
struct Foo {
bar: String,
}
-impl fmt::Debug for Foo {
- $0fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl core::fmt::Debug for Foo {
+ $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Foo").field("bar", &self.bar).finish()
}
}
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;
+//- minicore: fmt
+#[derive(Debu$0g)]
+struct Foo(String, usize);
+"#,
+ r#"struct Foo(String, usize);
+
+impl core::fmt::Debug for Foo {
+ $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ f.debug_tuple("Foo").field(&self.0).field(&self.1).finish()
}
}
+"#,
+ )
+ }
+ #[test]
+ fn add_custom_impl_debug_empty_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: fmt
+#[derive(Debu$0g)]
+struct Foo;
+"#,
+ r#"
+struct Foo;
+impl core::fmt::Debug for Foo {
+ $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ f.debug_struct("Foo").finish()
+ }
+}
+"#,
+ )
+ }
+ #[test]
+ fn add_custom_impl_debug_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: fmt
#[derive(Debu$0g)]
-struct Foo(String, usize);
+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 core::fmt::Debug for Foo {
+ $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ match self {
+ Self::Bar => write!(f, "Bar"),
+ Self::Baz => write!(f, "Baz"),
+ }
}
}
+"#,
+ )
+ }
-struct Foo(String, usize);
+ #[test]
+ fn add_custom_impl_debug_tuple_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: fmt
+#[derive(Debu$0g)]
+enum Foo {
+ Bar(usize, usize),
+ Baz,
+}
+"#,
+ r#"
+enum Foo {
+ Bar(usize, usize),
+ Baz,
+}
-impl fmt::Debug for Foo {
- $0fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_tuple("Foo").field(&self.0).field(&self.1).finish()
+impl core::fmt::Debug for Foo {
+ $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ match self {
+ Self::Bar(arg0, arg1) => f.debug_tuple("Bar").field(arg0).field(arg1).finish(),
+ Self::Baz => write!(f, "Baz"),
+ }
}
}
"#,
)
}
#[test]
- fn add_custom_impl_debug_empty_struct() {
+ fn add_custom_impl_debug_record_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;
+//- minicore: fmt
+#[derive(Debu$0g)]
+enum Foo {
+ Bar {
+ baz: usize,
+ qux: usize,
+ },
+ Baz,
+}
+"#,
+ r#"
+enum Foo {
+ Bar {
+ baz: usize,
+ qux: usize,
+ },
+ Baz,
+}
+
+impl core::fmt::Debug for Foo {
+ $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ match self {
+ Self::Bar { baz, qux } => f.debug_struct("Bar").field("baz", baz).field("qux", qux).finish(),
+ Self::Baz => write!(f, "Baz"),
+ }
}
}
+"#,
+ )
+ }
+ #[test]
+ fn add_custom_impl_default_record_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: default
+#[derive(Defau$0lt)]
+struct Foo {
+ foo: usize,
+}
+"#,
+ r#"
+struct Foo {
+ foo: usize,
+}
-#[derive(Debu$0g)]
+impl Default for Foo {
+ $0fn default() -> Self {
+ Self { foo: Default::default() }
+ }
+}
+"#,
+ )
+ }
+ #[test]
+ fn add_custom_impl_default_tuple_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: default
+#[derive(Defau$0lt)]
+struct Foo(usize);
+"#,
+ r#"
+struct Foo(usize);
+
+impl Default for Foo {
+ $0fn default() -> Self {
+ Self(Default::default())
+ }
+}
+"#,
+ )
+ }
+ #[test]
+ fn add_custom_impl_default_empty_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: default
+#[derive(Defau$0lt)]
struct Foo;
"#,
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;
+struct Foo;
+
+impl Default for Foo {
+ $0fn default() -> Self {
+ Self { }
}
}
+"#,
+ )
+ }
-struct Foo;
+ #[test]
+ fn add_custom_impl_hash_record_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: hash
+#[derive(Has$0h)]
+struct Foo {
+ bin: usize,
+ bar: usize,
+}
+"#,
+ r#"
+struct Foo {
+ bin: usize,
+ bar: usize,
+}
-impl fmt::Debug for Foo {
- $0fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Foo").finish()
+impl core::hash::Hash for Foo {
+ $0fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+ self.bin.hash(state);
+ self.bar.hash(state);
}
}
"#,
)
}
+
#[test]
- fn add_custom_impl_debug_enum() {
+ fn add_custom_impl_hash_tuple_struct() {
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;
+//- minicore: hash
+#[derive(Has$0h)]
+struct Foo(usize, usize);
+"#,
+ r#"
+struct Foo(usize, usize);
+
+impl core::hash::Hash for Foo {
+ $0fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+ self.0.hash(state);
+ self.1.hash(state);
}
}
+"#,
+ )
+ }
-#[derive(Debu$0g)]
+ #[test]
+ fn add_custom_impl_hash_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: hash
+#[derive(Has$0h)]
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 core::hash::Hash for Foo {
+ $0fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+ core::mem::discriminant(self).hash(state);
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_clone_record_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: clone
+#[derive(Clo$0ne)]
+struct Foo {
+ bin: usize,
+ bar: usize,
+}
+"#,
+ r#"
+struct Foo {
+ bin: usize,
+ bar: usize,
+}
+
+impl Clone for Foo {
+ $0fn clone(&self) -> Self {
+ Self { bin: self.bin.clone(), bar: self.bar.clone() }
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_clone_tuple_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: clone
+#[derive(Clo$0ne)]
+struct Foo(usize, usize);
+"#,
+ r#"
+struct Foo(usize, usize);
+
+impl Clone for Foo {
+ $0fn clone(&self) -> Self {
+ Self(self.0.clone(), self.1.clone())
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_clone_empty_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: clone
+#[derive(Clo$0ne)]
+struct Foo;
+"#,
+ r#"
+struct Foo;
+
+impl Clone for Foo {
+ $0fn clone(&self) -> Self {
+ Self { }
}
}
+"#,
+ )
+ }
+ #[test]
+ fn add_custom_impl_clone_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: clone
+#[derive(Clo$0ne)]
+enum Foo {
+ Bar,
+ Baz,
+}
+"#,
+ r#"
enum Foo {
Bar,
Baz,
}
-impl fmt::Debug for Foo {
- $0fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl Clone for Foo {
+ $0fn clone(&self) -> Self {
match self {
- Self::Bar => write!(f, "Bar"),
- Self::Baz => write!(f, "Baz"),
+ Self::Bar => Self::Bar,
+ Self::Baz => Self::Baz,
+ }
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_clone_tuple_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: clone
+#[derive(Clo$0ne)]
+enum Foo {
+ Bar(String),
+ Baz,
+}
+"#,
+ r#"
+enum Foo {
+ Bar(String),
+ Baz,
+}
+
+impl Clone for Foo {
+ $0fn clone(&self) -> Self {
+ match self {
+ Self::Bar(arg0) => Self::Bar(arg0.clone()),
+ Self::Baz => Self::Baz,
+ }
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_clone_record_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: clone
+#[derive(Clo$0ne)]
+enum Foo {
+ Bar {
+ bin: String,
+ },
+ Baz,
+}
+"#,
+ r#"
+enum Foo {
+ Bar {
+ bin: String,
+ },
+ Baz,
+}
+
+impl Clone for Foo {
+ $0fn clone(&self) -> Self {
+ match self {
+ Self::Bar { bin } => Self::Bar { bin: bin.clone() },
+ Self::Baz => Self::Baz,
+ }
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_ord_record_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: ord
+#[derive(Partial$0Ord)]
+struct Foo {
+ bin: usize,
+}
+"#,
+ r#"
+struct Foo {
+ bin: usize,
+}
+
+impl PartialOrd for Foo {
+ $0fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ self.bin.partial_cmp(other.bin)
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_ord_record_struct_multi_field() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: ord
+#[derive(Partial$0Ord)]
+struct Foo {
+ bin: usize,
+ bar: usize,
+ baz: usize,
+}
+"#,
+ r#"
+struct Foo {
+ bin: usize,
+ bar: usize,
+ baz: usize,
+}
+
+impl PartialOrd for Foo {
+ $0fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ (self.bin, self.bar, self.baz).partial_cmp((other.bin, other.bar, other.baz))
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_ord_tuple_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: ord
+#[derive(Partial$0Ord)]
+struct Foo(usize, usize, usize);
+"#,
+ r#"
+struct Foo(usize, usize, usize);
+
+impl PartialOrd for Foo {
+ $0fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ (self.0, self.1, self.2).partial_cmp((other.0, other.1, other.2))
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_ord_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: ord
+#[derive(Partial$0Ord)]
+enum Foo {
+ Bin,
+ Bar,
+ Baz,
+}
+"#,
+ r#"
+enum Foo {
+ Bin,
+ Bar,
+ Baz,
+}
+
+impl PartialOrd for Foo {
+ $0fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ core::mem::discriminant(self).partial_cmp(core::mem::discriminant(other))
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_ord_record_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: ord
+#[derive(Partial$0Ord)]
+enum Foo {
+ Bar {
+ bin: String,
+ },
+ Baz {
+ qux: String,
+ fez: String,
+ },
+ Qux {},
+ Bin,
+}
+"#,
+ r#"
+enum Foo {
+ Bar {
+ bin: String,
+ },
+ Baz {
+ qux: String,
+ fez: String,
+ },
+ Qux {},
+ Bin,
+}
+
+impl PartialOrd for Foo {
+ $0fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ match (self, other) {
+ (Self::Bar { bin: l_bin }, Self::Bar { bin: r_bin }) => l_bin.partial_cmp(r_bin),
+ (Self::Baz { qux: l_qux, fez: l_fez }, Self::Baz { qux: r_qux, fez: r_fez }) => {
+ (l_qux, l_fez).partial_cmp((r_qux, r_fez))
+ }
+ _ => core::mem::discriminant(self).partial_cmp(core::mem::discriminant(other)),
+ }
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_ord_tuple_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: ord
+#[derive(Partial$0Ord)]
+enum Foo {
+ Bar(String),
+ Baz(String, String),
+ Qux(),
+ Bin,
+}
+"#,
+ r#"
+enum Foo {
+ Bar(String),
+ Baz(String, String),
+ Qux(),
+ Bin,
+}
+
+impl PartialOrd for Foo {
+ $0fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ match (self, other) {
+ (Self::Bar(l0), Self::Bar(r0)) => l0.partial_cmp(r0),
+ (Self::Baz(l0, l1), Self::Baz(r0, r1)) => {
+ (l0, l1).partial_cmp((r0, r1))
+ }
+ _ => core::mem::discriminant(self).partial_cmp(core::mem::discriminant(other)),
+ }
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_eq_record_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: eq
+#[derive(Partial$0Eq)]
+struct Foo {
+ bin: usize,
+ bar: usize,
+}
+"#,
+ r#"
+struct Foo {
+ bin: usize,
+ bar: usize,
+}
+
+impl PartialEq for Foo {
+ $0fn eq(&self, other: &Self) -> bool {
+ self.bin == other.bin && self.bar == other.bar
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_eq_tuple_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: eq
+#[derive(Partial$0Eq)]
+struct Foo(usize, usize);
+"#,
+ r#"
+struct Foo(usize, usize);
+
+impl PartialEq for Foo {
+ $0fn eq(&self, other: &Self) -> bool {
+ self.0 == other.0 && self.1 == other.1
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_eq_empty_struct() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: eq
+#[derive(Partial$0Eq)]
+struct Foo;
+"#,
+ r#"
+struct Foo;
+
+impl PartialEq for Foo {
+ $0fn eq(&self, other: &Self) -> bool {
+ true
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_eq_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: eq
+#[derive(Partial$0Eq)]
+enum Foo {
+ Bar,
+ Baz,
+}
+"#,
+ r#"
+enum Foo {
+ Bar,
+ Baz,
+}
+
+impl PartialEq for Foo {
+ $0fn eq(&self, other: &Self) -> bool {
+ core::mem::discriminant(self) == core::mem::discriminant(other)
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_eq_tuple_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: eq
+#[derive(Partial$0Eq)]
+enum Foo {
+ Bar(String),
+ Baz,
+}
+"#,
+ r#"
+enum Foo {
+ Bar(String),
+ Baz,
+}
+
+impl PartialEq for Foo {
+ $0fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (Self::Bar(l0), Self::Bar(r0)) => l0 == r0,
+ _ => core::mem::discriminant(self) == core::mem::discriminant(other),
+ }
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn add_custom_impl_partial_eq_record_enum() {
+ check_assist(
+ replace_derive_with_manual_impl,
+ r#"
+//- minicore: eq
+#[derive(Partial$0Eq)]
+enum Foo {
+ Bar {
+ bin: String,
+ },
+ Baz {
+ qux: String,
+ fez: String,
+ },
+ Qux {},
+ Bin,
+}
+"#,
+ r#"
+enum Foo {
+ Bar {
+ bin: String,
+ },
+ Baz {
+ qux: String,
+ fez: String,
+ },
+ Qux {},
+ Bin,
+}
+
+impl PartialEq for Foo {
+ $0fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (Self::Bar { bin: l_bin }, Self::Bar { bin: r_bin }) => l_bin == r_bin,
+ (Self::Baz { qux: l_qux, fez: l_fez }, Self::Baz { qux: r_qux, fez: r_fez }) => l_qux == r_qux && l_fez == r_fez,
+ _ => core::mem::discriminant(self) == core::mem::discriminant(other),
}
}
}