]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
Replaced fold with for loop
[rust.git] / crates / ide_assists / src / handlers / replace_derive_with_manual_impl.rs
1 use hir::ModuleDef;
2 use ide_db::helpers::insert_whitespace_into_node::insert_ws_into;
3 use ide_db::helpers::{
4     get_path_at_cursor_in_tt, import_assets::NameToImport, mod_path_to_ast,
5     parse_tt_as_comma_sep_paths,
6 };
7 use ide_db::items_locator;
8 use itertools::Itertools;
9 use syntax::{
10     ast::{self, AstNode, AstToken, HasName},
11     SyntaxKind::WHITESPACE,
12 };
13
14 use crate::{
15     assist_context::{AssistBuilder, AssistContext, Assists},
16     utils::{
17         add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body,
18         generate_trait_impl_text, render_snippet, Cursor, DefaultMethods,
19     },
20     AssistId, AssistKind,
21 };
22
23 // Assist: replace_derive_with_manual_impl
24 //
25 // Converts a `derive` impl into a manual one.
26 //
27 // ```
28 // # trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
29 // #[derive(Deb$0ug, Display)]
30 // struct S;
31 // ```
32 // ->
33 // ```
34 // # trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
35 // #[derive(Display)]
36 // struct S;
37 //
38 // impl Debug for S {
39 //     $0fn fmt(&self, f: &mut Formatter) -> Result<()> {
40 //         f.debug_struct("S").finish()
41 //     }
42 // }
43 // ```
44 pub(crate) fn replace_derive_with_manual_impl(
45     acc: &mut Assists,
46     ctx: &AssistContext,
47 ) -> Option<()> {
48     let attr = ctx.find_node_at_offset::<ast::Attr>()?;
49     let (name, args) = attr.as_simple_call()?;
50     if name != "derive" {
51         return None;
52     }
53
54     if !args.syntax().text_range().contains(ctx.offset()) {
55         cov_mark::hit!(outside_of_attr_args);
56         return None;
57     }
58
59     let ident = args.syntax().token_at_offset(ctx.offset()).find_map(ast::Ident::cast)?;
60     let trait_path = get_path_at_cursor_in_tt(&ident)?;
61     let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;
62
63     let current_module = ctx.sema.scope(adt.syntax()).module()?;
64     let current_crate = current_module.krate();
65
66     let found_traits = items_locator::items_with_name(
67         &ctx.sema,
68         current_crate,
69         NameToImport::exact_case_sensitive(trait_path.segments().last()?.to_string()),
70         items_locator::AssocItemSearch::Exclude,
71         Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT.inner()),
72     )
73     .filter_map(|item| match item.as_module_def()? {
74         ModuleDef::Trait(trait_) => Some(trait_),
75         _ => None,
76     })
77     .flat_map(|trait_| {
78         current_module
79             .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_))
80             .as_ref()
81             .map(mod_path_to_ast)
82             .zip(Some(trait_))
83     });
84
85     let mut no_traits_found = true;
86     let current_derives = parse_tt_as_comma_sep_paths(args.clone())?;
87     let current_derives = current_derives.as_slice();
88     for (replace_trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) {
89         add_assist(
90             acc,
91             ctx,
92             &attr,
93             &current_derives,
94             &args,
95             &trait_path,
96             &replace_trait_path,
97             Some(trait_),
98             &adt,
99         )?;
100     }
101     if no_traits_found {
102         add_assist(acc, ctx, &attr, &current_derives, &args, &trait_path, &trait_path, None, &adt)?;
103     }
104     Some(())
105 }
106
107 fn add_assist(
108     acc: &mut Assists,
109     ctx: &AssistContext,
110     attr: &ast::Attr,
111     old_derives: &[ast::Path],
112     old_tree: &ast::TokenTree,
113     old_trait_path: &ast::Path,
114     replace_trait_path: &ast::Path,
115     trait_: Option<hir::Trait>,
116     adt: &ast::Adt,
117 ) -> Option<()> {
118     let target = attr.syntax().text_range();
119     let annotated_name = adt.name()?;
120     let label = format!("Convert to manual `impl {} for {}`", replace_trait_path, annotated_name);
121
122     acc.add(
123         AssistId("replace_derive_with_manual_impl", AssistKind::Refactor),
124         label,
125         target,
126         |builder| {
127             let insert_pos = adt.syntax().text_range().end();
128             let impl_def_with_items =
129                 impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, replace_trait_path);
130             update_attribute(builder, old_derives, old_tree, old_trait_path, attr);
131             let trait_path = format!("{}", replace_trait_path);
132             match (ctx.config.snippet_cap, impl_def_with_items) {
133                 (None, _) => {
134                     builder.insert(insert_pos, generate_trait_impl_text(adt, &trait_path, ""))
135                 }
136                 (Some(cap), None) => builder.insert_snippet(
137                     cap,
138                     insert_pos,
139                     generate_trait_impl_text(adt, &trait_path, "    $0"),
140                 ),
141                 (Some(cap), Some((impl_def, first_assoc_item))) => {
142                     let mut cursor = Cursor::Before(first_assoc_item.syntax());
143                     let placeholder;
144                     if let ast::AssocItem::Fn(ref func) = first_assoc_item {
145                         if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
146                         {
147                             if m.syntax().text() == "todo!()" {
148                                 placeholder = m;
149                                 cursor = Cursor::Replace(placeholder.syntax());
150                             }
151                         }
152                     }
153
154                     builder.insert_snippet(
155                         cap,
156                         insert_pos,
157                         format!("\n\n{}", render_snippet(cap, impl_def.syntax(), cursor)),
158                     )
159                 }
160             };
161         },
162     )
163 }
164
165 fn impl_def_from_trait(
166     sema: &hir::Semantics<ide_db::RootDatabase>,
167     adt: &ast::Adt,
168     annotated_name: &ast::Name,
169     trait_: Option<hir::Trait>,
170     trait_path: &ast::Path,
171 ) -> Option<(ast::Impl, ast::AssocItem)> {
172     let trait_ = trait_?;
173     let target_scope = sema.scope(annotated_name.syntax());
174     let trait_items = filter_assoc_items(sema, &trait_.items(sema.db), DefaultMethods::No);
175     if trait_items.is_empty() {
176         return None;
177     }
178     let impl_def = {
179         use syntax::ast::Impl;
180         let text = generate_trait_impl_text(adt, trait_path.to_string().as_str(), "");
181         let parse = syntax::SourceFile::parse(&text);
182         let node = match parse.tree().syntax().descendants().find_map(Impl::cast) {
183             Some(it) => it,
184             None => {
185                 panic!(
186                     "Failed to make ast node `{}` from text {}",
187                     std::any::type_name::<Impl>(),
188                     text
189                 )
190             }
191         };
192         let node = node.clone_subtree();
193         assert_eq!(node.syntax().text_range().start(), 0.into());
194         node
195     };
196
197     let trait_items = trait_items
198         .into_iter()
199         .map(|it| {
200             if sema.hir_file_for(it.syntax()).is_macro() {
201                 if let Some(it) = ast::AssocItem::cast(insert_ws_into(it.syntax().clone())) {
202                     return it;
203                 }
204             }
205             it.clone_for_update()
206         })
207         .collect();
208     let (impl_def, first_assoc_item) =
209         add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope);
210
211     // Generate a default `impl` function body for the derived trait.
212     if let ast::AssocItem::Fn(ref func) = first_assoc_item {
213         let _ = gen_trait_fn_body(func, trait_path, adt);
214     };
215
216     Some((impl_def, first_assoc_item))
217 }
218
219 fn update_attribute(
220     builder: &mut AssistBuilder,
221     old_derives: &[ast::Path],
222     old_tree: &ast::TokenTree,
223     old_trait_path: &ast::Path,
224     attr: &ast::Attr,
225 ) {
226     let new_derives = old_derives
227         .iter()
228         .filter(|t| t.to_string() != old_trait_path.to_string())
229         .collect::<Vec<_>>();
230     let has_more_derives = !new_derives.is_empty();
231
232     if has_more_derives {
233         let new_derives = format!("({})", new_derives.iter().format(", "));
234         builder.replace(old_tree.syntax().text_range(), new_derives);
235     } else {
236         let attr_range = attr.syntax().text_range();
237         builder.delete(attr_range);
238
239         if let Some(line_break_range) = attr
240             .syntax()
241             .next_sibling_or_token()
242             .filter(|t| t.kind() == WHITESPACE)
243             .map(|t| t.text_range())
244         {
245             builder.delete(line_break_range);
246         }
247     }
248 }
249
250 #[cfg(test)]
251 mod tests {
252     use crate::tests::{check_assist, check_assist_not_applicable};
253
254     use super::*;
255
256     #[test]
257     fn add_custom_impl_debug_record_struct() {
258         check_assist(
259             replace_derive_with_manual_impl,
260             r#"
261 //- minicore: fmt
262 #[derive(Debu$0g)]
263 struct Foo {
264     bar: String,
265 }
266 "#,
267             r#"
268 struct Foo {
269     bar: String,
270 }
271
272 impl core::fmt::Debug for Foo {
273     $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
274         f.debug_struct("Foo").field("bar", &self.bar).finish()
275     }
276 }
277 "#,
278         )
279     }
280     #[test]
281     fn add_custom_impl_debug_tuple_struct() {
282         check_assist(
283             replace_derive_with_manual_impl,
284             r#"
285 //- minicore: fmt
286 #[derive(Debu$0g)]
287 struct Foo(String, usize);
288 "#,
289             r#"struct Foo(String, usize);
290
291 impl core::fmt::Debug for Foo {
292     $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
293         f.debug_tuple("Foo").field(&self.0).field(&self.1).finish()
294     }
295 }
296 "#,
297         )
298     }
299     #[test]
300     fn add_custom_impl_debug_empty_struct() {
301         check_assist(
302             replace_derive_with_manual_impl,
303             r#"
304 //- minicore: fmt
305 #[derive(Debu$0g)]
306 struct Foo;
307 "#,
308             r#"
309 struct Foo;
310
311 impl core::fmt::Debug for Foo {
312     $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
313         f.debug_struct("Foo").finish()
314     }
315 }
316 "#,
317         )
318     }
319     #[test]
320     fn add_custom_impl_debug_enum() {
321         check_assist(
322             replace_derive_with_manual_impl,
323             r#"
324 //- minicore: fmt
325 #[derive(Debu$0g)]
326 enum Foo {
327     Bar,
328     Baz,
329 }
330 "#,
331             r#"
332 enum Foo {
333     Bar,
334     Baz,
335 }
336
337 impl core::fmt::Debug for Foo {
338     $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
339         match self {
340             Self::Bar => write!(f, "Bar"),
341             Self::Baz => write!(f, "Baz"),
342         }
343     }
344 }
345 "#,
346         )
347     }
348
349     #[test]
350     fn add_custom_impl_debug_tuple_enum() {
351         check_assist(
352             replace_derive_with_manual_impl,
353             r#"
354 //- minicore: fmt
355 #[derive(Debu$0g)]
356 enum Foo {
357     Bar(usize, usize),
358     Baz,
359 }
360 "#,
361             r#"
362 enum Foo {
363     Bar(usize, usize),
364     Baz,
365 }
366
367 impl core::fmt::Debug for Foo {
368     $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
369         match self {
370             Self::Bar(arg0, arg1) => f.debug_tuple("Bar").field(arg0).field(arg1).finish(),
371             Self::Baz => write!(f, "Baz"),
372         }
373     }
374 }
375 "#,
376         )
377     }
378     #[test]
379     fn add_custom_impl_debug_record_enum() {
380         check_assist(
381             replace_derive_with_manual_impl,
382             r#"
383 //- minicore: fmt
384 #[derive(Debu$0g)]
385 enum Foo {
386     Bar {
387         baz: usize,
388         qux: usize,
389     },
390     Baz,
391 }
392 "#,
393             r#"
394 enum Foo {
395     Bar {
396         baz: usize,
397         qux: usize,
398     },
399     Baz,
400 }
401
402 impl core::fmt::Debug for Foo {
403     $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
404         match self {
405             Self::Bar { baz, qux } => f.debug_struct("Bar").field("baz", baz).field("qux", qux).finish(),
406             Self::Baz => write!(f, "Baz"),
407         }
408     }
409 }
410 "#,
411         )
412     }
413     #[test]
414     fn add_custom_impl_default_record_struct() {
415         check_assist(
416             replace_derive_with_manual_impl,
417             r#"
418 //- minicore: default
419 #[derive(Defau$0lt)]
420 struct Foo {
421     foo: usize,
422 }
423 "#,
424             r#"
425 struct Foo {
426     foo: usize,
427 }
428
429 impl Default for Foo {
430     $0fn default() -> Self {
431         Self { foo: Default::default() }
432     }
433 }
434 "#,
435         )
436     }
437     #[test]
438     fn add_custom_impl_default_tuple_struct() {
439         check_assist(
440             replace_derive_with_manual_impl,
441             r#"
442 //- minicore: default
443 #[derive(Defau$0lt)]
444 struct Foo(usize);
445 "#,
446             r#"
447 struct Foo(usize);
448
449 impl Default for Foo {
450     $0fn default() -> Self {
451         Self(Default::default())
452     }
453 }
454 "#,
455         )
456     }
457     #[test]
458     fn add_custom_impl_default_empty_struct() {
459         check_assist(
460             replace_derive_with_manual_impl,
461             r#"
462 //- minicore: default
463 #[derive(Defau$0lt)]
464 struct Foo;
465 "#,
466             r#"
467 struct Foo;
468
469 impl Default for Foo {
470     $0fn default() -> Self {
471         Self {  }
472     }
473 }
474 "#,
475         )
476     }
477
478     #[test]
479     fn add_custom_impl_hash_record_struct() {
480         check_assist(
481             replace_derive_with_manual_impl,
482             r#"
483 //- minicore: hash
484 #[derive(Has$0h)]
485 struct Foo {
486     bin: usize,
487     bar: usize,
488 }
489 "#,
490             r#"
491 struct Foo {
492     bin: usize,
493     bar: usize,
494 }
495
496 impl core::hash::Hash for Foo {
497     $0fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
498         self.bin.hash(state);
499         self.bar.hash(state);
500     }
501 }
502 "#,
503         )
504     }
505
506     #[test]
507     fn add_custom_impl_hash_tuple_struct() {
508         check_assist(
509             replace_derive_with_manual_impl,
510             r#"
511 //- minicore: hash
512 #[derive(Has$0h)]
513 struct Foo(usize, usize);
514 "#,
515             r#"
516 struct Foo(usize, usize);
517
518 impl core::hash::Hash for Foo {
519     $0fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
520         self.0.hash(state);
521         self.1.hash(state);
522     }
523 }
524 "#,
525         )
526     }
527
528     #[test]
529     fn add_custom_impl_hash_enum() {
530         check_assist(
531             replace_derive_with_manual_impl,
532             r#"
533 //- minicore: hash
534 #[derive(Has$0h)]
535 enum Foo {
536     Bar,
537     Baz,
538 }
539 "#,
540             r#"
541 enum Foo {
542     Bar,
543     Baz,
544 }
545
546 impl core::hash::Hash for Foo {
547     $0fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
548         core::mem::discriminant(self).hash(state);
549     }
550 }
551 "#,
552         )
553     }
554
555     #[test]
556     fn add_custom_impl_clone_record_struct() {
557         check_assist(
558             replace_derive_with_manual_impl,
559             r#"
560 //- minicore: clone
561 #[derive(Clo$0ne)]
562 struct Foo {
563     bin: usize,
564     bar: usize,
565 }
566 "#,
567             r#"
568 struct Foo {
569     bin: usize,
570     bar: usize,
571 }
572
573 impl Clone for Foo {
574     $0fn clone(&self) -> Self {
575         Self { bin: self.bin.clone(), bar: self.bar.clone() }
576     }
577 }
578 "#,
579         )
580     }
581
582     #[test]
583     fn add_custom_impl_clone_tuple_struct() {
584         check_assist(
585             replace_derive_with_manual_impl,
586             r#"
587 //- minicore: clone
588 #[derive(Clo$0ne)]
589 struct Foo(usize, usize);
590 "#,
591             r#"
592 struct Foo(usize, usize);
593
594 impl Clone for Foo {
595     $0fn clone(&self) -> Self {
596         Self(self.0.clone(), self.1.clone())
597     }
598 }
599 "#,
600         )
601     }
602
603     #[test]
604     fn add_custom_impl_clone_empty_struct() {
605         check_assist(
606             replace_derive_with_manual_impl,
607             r#"
608 //- minicore: clone
609 #[derive(Clo$0ne)]
610 struct Foo;
611 "#,
612             r#"
613 struct Foo;
614
615 impl Clone for Foo {
616     $0fn clone(&self) -> Self {
617         Self {  }
618     }
619 }
620 "#,
621         )
622     }
623
624     #[test]
625     fn add_custom_impl_clone_enum() {
626         check_assist(
627             replace_derive_with_manual_impl,
628             r#"
629 //- minicore: clone
630 #[derive(Clo$0ne)]
631 enum Foo {
632     Bar,
633     Baz,
634 }
635 "#,
636             r#"
637 enum Foo {
638     Bar,
639     Baz,
640 }
641
642 impl Clone for Foo {
643     $0fn clone(&self) -> Self {
644         match self {
645             Self::Bar => Self::Bar,
646             Self::Baz => Self::Baz,
647         }
648     }
649 }
650 "#,
651         )
652     }
653
654     #[test]
655     fn add_custom_impl_clone_tuple_enum() {
656         check_assist(
657             replace_derive_with_manual_impl,
658             r#"
659 //- minicore: clone
660 #[derive(Clo$0ne)]
661 enum Foo {
662     Bar(String),
663     Baz,
664 }
665 "#,
666             r#"
667 enum Foo {
668     Bar(String),
669     Baz,
670 }
671
672 impl Clone for Foo {
673     $0fn clone(&self) -> Self {
674         match self {
675             Self::Bar(arg0) => Self::Bar(arg0.clone()),
676             Self::Baz => Self::Baz,
677         }
678     }
679 }
680 "#,
681         )
682     }
683
684     #[test]
685     fn add_custom_impl_clone_record_enum() {
686         check_assist(
687             replace_derive_with_manual_impl,
688             r#"
689 //- minicore: clone
690 #[derive(Clo$0ne)]
691 enum Foo {
692     Bar {
693         bin: String,
694     },
695     Baz,
696 }
697 "#,
698             r#"
699 enum Foo {
700     Bar {
701         bin: String,
702     },
703     Baz,
704 }
705
706 impl Clone for Foo {
707     $0fn clone(&self) -> Self {
708         match self {
709             Self::Bar { bin } => Self::Bar { bin: bin.clone() },
710             Self::Baz => Self::Baz,
711         }
712     }
713 }
714 "#,
715         )
716     }
717
718     #[test]
719     fn add_custom_impl_partial_ord_record_struct() {
720         check_assist(
721             replace_derive_with_manual_impl,
722             r#"
723 //- minicore: ord
724 #[derive(Partial$0Ord)]
725 struct Foo {
726     bin: usize,
727 }
728 "#,
729             r#"
730 struct Foo {
731     bin: usize,
732 }
733
734 impl PartialOrd for Foo {
735     $0fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
736         self.bin.partial_cmp(&other.bin)
737     }
738 }
739 "#,
740         )
741     }
742
743     #[test]
744     fn add_custom_impl_partial_ord_record_struct_multi_field() {
745         check_assist(
746             replace_derive_with_manual_impl,
747             r#"
748 //- minicore: ord
749 #[derive(Partial$0Ord)]
750 struct Foo {
751     bin: usize,
752     bar: usize,
753     baz: usize,
754 }
755 "#,
756             r#"
757 struct Foo {
758     bin: usize,
759     bar: usize,
760     baz: usize,
761 }
762
763 impl PartialOrd for Foo {
764     $0fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
765         match self.bin.partial_cmp(&other.bin) {
766             Some(core::cmp::Ordering::Equal) => {}
767             ord => return ord,
768         }
769         match self.bar.partial_cmp(&other.bar) {
770             Some(core::cmp::Ordering::Equal) => {}
771             ord => return ord,
772         }
773         self.baz.partial_cmp(&other.baz)
774     }
775 }
776 "#,
777         )
778     }
779
780     #[test]
781     fn add_custom_impl_partial_ord_tuple_struct() {
782         check_assist(
783             replace_derive_with_manual_impl,
784             r#"
785 //- minicore: ord
786 #[derive(Partial$0Ord)]
787 struct Foo(usize, usize, usize);
788 "#,
789             r#"
790 struct Foo(usize, usize, usize);
791
792 impl PartialOrd for Foo {
793     $0fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
794         match self.0.partial_cmp(&other.0) {
795             Some(core::cmp::Ordering::Equal) => {}
796             ord => return ord,
797         }
798         match self.1.partial_cmp(&other.1) {
799             Some(core::cmp::Ordering::Equal) => {}
800             ord => return ord,
801         }
802         self.2.partial_cmp(&other.2)
803     }
804 }
805 "#,
806         )
807     }
808
809     #[test]
810     fn add_custom_impl_partial_eq_record_struct() {
811         check_assist(
812             replace_derive_with_manual_impl,
813             r#"
814 //- minicore: eq
815 #[derive(Partial$0Eq)]
816 struct Foo {
817     bin: usize,
818     bar: usize,
819 }
820 "#,
821             r#"
822 struct Foo {
823     bin: usize,
824     bar: usize,
825 }
826
827 impl PartialEq for Foo {
828     $0fn eq(&self, other: &Self) -> bool {
829         self.bin == other.bin && self.bar == other.bar
830     }
831 }
832 "#,
833         )
834     }
835
836     #[test]
837     fn add_custom_impl_partial_eq_tuple_struct() {
838         check_assist(
839             replace_derive_with_manual_impl,
840             r#"
841 //- minicore: eq
842 #[derive(Partial$0Eq)]
843 struct Foo(usize, usize);
844 "#,
845             r#"
846 struct Foo(usize, usize);
847
848 impl PartialEq for Foo {
849     $0fn eq(&self, other: &Self) -> bool {
850         self.0 == other.0 && self.1 == other.1
851     }
852 }
853 "#,
854         )
855     }
856
857     #[test]
858     fn add_custom_impl_partial_eq_empty_struct() {
859         check_assist(
860             replace_derive_with_manual_impl,
861             r#"
862 //- minicore: eq
863 #[derive(Partial$0Eq)]
864 struct Foo;
865 "#,
866             r#"
867 struct Foo;
868
869 impl PartialEq for Foo {
870     $0fn eq(&self, other: &Self) -> bool {
871         true
872     }
873 }
874 "#,
875         )
876     }
877
878     #[test]
879     fn add_custom_impl_partial_eq_enum() {
880         check_assist(
881             replace_derive_with_manual_impl,
882             r#"
883 //- minicore: eq
884 #[derive(Partial$0Eq)]
885 enum Foo {
886     Bar,
887     Baz,
888 }
889 "#,
890             r#"
891 enum Foo {
892     Bar,
893     Baz,
894 }
895
896 impl PartialEq for Foo {
897     $0fn eq(&self, other: &Self) -> bool {
898         core::mem::discriminant(self) == core::mem::discriminant(other)
899     }
900 }
901 "#,
902         )
903     }
904
905     #[test]
906     fn add_custom_impl_partial_eq_tuple_enum() {
907         check_assist(
908             replace_derive_with_manual_impl,
909             r#"
910 //- minicore: eq
911 #[derive(Partial$0Eq)]
912 enum Foo {
913     Bar(String),
914     Baz,
915 }
916 "#,
917             r#"
918 enum Foo {
919     Bar(String),
920     Baz,
921 }
922
923 impl PartialEq for Foo {
924     $0fn eq(&self, other: &Self) -> bool {
925         match (self, other) {
926             (Self::Bar(l0), Self::Bar(r0)) => l0 == r0,
927             _ => core::mem::discriminant(self) == core::mem::discriminant(other),
928         }
929     }
930 }
931 "#,
932         )
933     }
934
935     #[test]
936     fn add_custom_impl_partial_eq_record_enum() {
937         check_assist(
938             replace_derive_with_manual_impl,
939             r#"
940 //- minicore: eq
941 #[derive(Partial$0Eq)]
942 enum Foo {
943     Bar {
944         bin: String,
945     },
946     Baz {
947         qux: String,
948         fez: String,
949     },
950     Qux {},
951     Bin,
952 }
953 "#,
954             r#"
955 enum Foo {
956     Bar {
957         bin: String,
958     },
959     Baz {
960         qux: String,
961         fez: String,
962     },
963     Qux {},
964     Bin,
965 }
966
967 impl PartialEq for Foo {
968     $0fn eq(&self, other: &Self) -> bool {
969         match (self, other) {
970             (Self::Bar { bin: l_bin }, Self::Bar { bin: r_bin }) => l_bin == r_bin,
971             (Self::Baz { qux: l_qux, fez: l_fez }, Self::Baz { qux: r_qux, fez: r_fez }) => l_qux == r_qux && l_fez == r_fez,
972             _ => core::mem::discriminant(self) == core::mem::discriminant(other),
973         }
974     }
975 }
976 "#,
977         )
978     }
979     #[test]
980     fn add_custom_impl_all() {
981         check_assist(
982             replace_derive_with_manual_impl,
983             r#"
984 mod foo {
985     pub trait Bar {
986         type Qux;
987         const Baz: usize = 42;
988         const Fez: usize;
989         fn foo();
990         fn bar() {}
991     }
992 }
993
994 #[derive($0Bar)]
995 struct Foo {
996     bar: String,
997 }
998 "#,
999             r#"
1000 mod foo {
1001     pub trait Bar {
1002         type Qux;
1003         const Baz: usize = 42;
1004         const Fez: usize;
1005         fn foo();
1006         fn bar() {}
1007     }
1008 }
1009
1010 struct Foo {
1011     bar: String,
1012 }
1013
1014 impl foo::Bar for Foo {
1015     $0type Qux;
1016
1017     const Baz: usize = 42;
1018
1019     const Fez: usize;
1020
1021     fn foo() {
1022         todo!()
1023     }
1024 }
1025 "#,
1026         )
1027     }
1028     #[test]
1029     fn add_custom_impl_for_unique_input() {
1030         check_assist(
1031             replace_derive_with_manual_impl,
1032             r#"
1033 #[derive(Debu$0g)]
1034 struct Foo {
1035     bar: String,
1036 }
1037             "#,
1038             r#"
1039 struct Foo {
1040     bar: String,
1041 }
1042
1043 impl Debug for Foo {
1044     $0
1045 }
1046             "#,
1047         )
1048     }
1049
1050     #[test]
1051     fn add_custom_impl_for_with_visibility_modifier() {
1052         check_assist(
1053             replace_derive_with_manual_impl,
1054             r#"
1055 #[derive(Debug$0)]
1056 pub struct Foo {
1057     bar: String,
1058 }
1059             "#,
1060             r#"
1061 pub struct Foo {
1062     bar: String,
1063 }
1064
1065 impl Debug for Foo {
1066     $0
1067 }
1068             "#,
1069         )
1070     }
1071
1072     #[test]
1073     fn add_custom_impl_when_multiple_inputs() {
1074         check_assist(
1075             replace_derive_with_manual_impl,
1076             r#"
1077 #[derive(Display, Debug$0, Serialize)]
1078 struct Foo {}
1079             "#,
1080             r#"
1081 #[derive(Display, Serialize)]
1082 struct Foo {}
1083
1084 impl Debug for Foo {
1085     $0
1086 }
1087             "#,
1088         )
1089     }
1090
1091     #[test]
1092     fn add_custom_impl_default_generic_record_struct() {
1093         check_assist(
1094             replace_derive_with_manual_impl,
1095             r#"
1096 //- minicore: default
1097 #[derive(Defau$0lt)]
1098 struct Foo<T, U> {
1099     foo: T,
1100     bar: U,
1101 }
1102 "#,
1103             r#"
1104 struct Foo<T, U> {
1105     foo: T,
1106     bar: U,
1107 }
1108
1109 impl<T, U> Default for Foo<T, U> {
1110     $0fn default() -> Self {
1111         Self { foo: Default::default(), bar: Default::default() }
1112     }
1113 }
1114 "#,
1115         )
1116     }
1117
1118     #[test]
1119     fn add_custom_impl_clone_generic_tuple_struct_with_bounds() {
1120         check_assist(
1121             replace_derive_with_manual_impl,
1122             r#"
1123 //- minicore: clone
1124 #[derive(Clo$0ne)]
1125 struct Foo<T: Clone>(T, usize);
1126 "#,
1127             r#"
1128 struct Foo<T: Clone>(T, usize);
1129
1130 impl<T: Clone> Clone for Foo<T> {
1131     $0fn clone(&self) -> Self {
1132         Self(self.0.clone(), self.1.clone())
1133     }
1134 }
1135 "#,
1136         )
1137     }
1138
1139     #[test]
1140     fn test_ignore_derive_macro_without_input() {
1141         check_assist_not_applicable(
1142             replace_derive_with_manual_impl,
1143             r#"
1144 #[derive($0)]
1145 struct Foo {}
1146             "#,
1147         )
1148     }
1149
1150     #[test]
1151     fn test_ignore_if_cursor_on_param() {
1152         check_assist_not_applicable(
1153             replace_derive_with_manual_impl,
1154             r#"
1155 #[derive$0(Debug)]
1156 struct Foo {}
1157             "#,
1158         );
1159
1160         check_assist_not_applicable(
1161             replace_derive_with_manual_impl,
1162             r#"
1163 #[derive(Debug)$0]
1164 struct Foo {}
1165             "#,
1166         )
1167     }
1168
1169     #[test]
1170     fn test_ignore_if_not_derive() {
1171         check_assist_not_applicable(
1172             replace_derive_with_manual_impl,
1173             r#"
1174 #[allow(non_camel_$0case_types)]
1175 struct Foo {}
1176             "#,
1177         )
1178     }
1179
1180     #[test]
1181     fn works_at_start_of_file() {
1182         cov_mark::check!(outside_of_attr_args);
1183         check_assist_not_applicable(
1184             replace_derive_with_manual_impl,
1185             r#"
1186 $0#[derive(Debug)]
1187 struct S;
1188             "#,
1189         );
1190     }
1191
1192     #[test]
1193     fn add_custom_impl_keep_path() {
1194         check_assist(
1195             replace_derive_with_manual_impl,
1196             r#"
1197 //- minicore: clone
1198 #[derive(std::fmt::Debug, Clo$0ne)]
1199 pub struct Foo;
1200 "#,
1201             r#"
1202 #[derive(std::fmt::Debug)]
1203 pub struct Foo;
1204
1205 impl Clone for Foo {
1206     $0fn clone(&self) -> Self {
1207         Self {  }
1208     }
1209 }
1210 "#,
1211         )
1212     }
1213
1214     #[test]
1215     fn add_custom_impl_replace_path() {
1216         check_assist(
1217             replace_derive_with_manual_impl,
1218             r#"
1219 //- minicore: fmt
1220 #[derive(core::fmt::Deb$0ug, Clone)]
1221 pub struct Foo;
1222 "#,
1223             r#"
1224 #[derive(Clone)]
1225 pub struct Foo;
1226
1227 impl core::fmt::Debug for Foo {
1228     $0fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1229         f.debug_struct("Foo").finish()
1230     }
1231 }
1232 "#,
1233         )
1234     }
1235 }