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 042f31e5c4d..5ba045d3c8f 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 @@ -160,8 +160,25 @@ fn impl_def_from_trait( if trait_items.is_empty() { return None; } - let impl_def = - make::impl_trait(trait_path.clone(), make::ext::ident_path(&annotated_name.text())); + let impl_def = { + use syntax::ast::Impl; + let text = generate_trait_impl_text(adt, trait_path.to_string().as_str(), ""); + let parse = syntax::SourceFile::parse(&text); + let node = match parse.tree().syntax().descendants().find_map(Impl::cast) { + Some(it) => it, + None => { + panic!( + "Failed to make ast node `{}` from text {}", + std::any::type_name::(), + text + ) + } + }; + let node = node.clone_subtree(); + assert_eq!(node.syntax().text_range().start(), 0.into()); + node + }; + let (impl_def, first_assoc_item) = add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope); @@ -1048,6 +1065,54 @@ impl Debug for Foo { ) } + #[test] + fn add_custom_impl_default_generic_record_struct() { + check_assist( + replace_derive_with_manual_impl, + r#" +//- minicore: default +#[derive(Defau$0lt)] +struct Foo { + foo: T, + bar: U, +} +"#, + r#" +struct Foo { + foo: T, + bar: U, +} + +impl Default for Foo { + $0fn default() -> Self { + Self { foo: Default::default(), bar: Default::default() } + } +} +"#, + ) + } + + #[test] + fn add_custom_impl_clone_generic_tuple_struct_with_bounds() { + check_assist( + replace_derive_with_manual_impl, + r#" +//- minicore: clone +#[derive(Clo$0ne)] +struct Foo(T, usize); +"#, + r#" +struct Foo(T, usize); + +impl Clone for Foo { + $0fn clone(&self) -> Self { + Self(self.0.clone(), self.1.clone()) + } +} +"#, + ) + } + #[test] fn test_ignore_derive_macro_without_input() { check_assist_not_applicable( diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index ed69973af92..e1938307cf3 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -149,8 +149,13 @@ pub fn impl_( ast_from_text(&format!("impl{} {}{} {{}}", params, ty, ty_params)) } -pub fn impl_trait(trait_: ast::Path, ty: ast::Path) -> ast::Impl { - ast_from_text(&format!("impl {} for {} {{}}", trait_, ty)) +pub fn impl_trait( + trait_: ast::Path, + ty: ast::Path, + ty_params: Option, +) -> ast::Impl { + let ty_params = ty_params.map_or_else(String::new, |params| params.to_string()); + ast_from_text(&format!("impl{2} {} for {}{2} {{}}", trait_, ty, ty_params)) } pub(crate) fn generic_arg_list() -> ast::GenericArgList {