Unnamed repository; edit this file 'description' to name the repository.
Merge #10734
10734: fix: add generic parameters in convert to manual impl assist r=Veykril a=TheDoctor314 Fixes #10041. Co-authored-by: TheDoctor314 <[email protected]>
bors[bot] 2021-11-16
parent 7e756ac · parent 58a24de · commit 6c7be6c
-rw-r--r--crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs69
-rw-r--r--crates/syntax/src/ast/make.rs9
2 files changed, 74 insertions, 4 deletions
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 042f31e5c4..5ba045d3c8 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::<Impl>(),
+ 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);
@@ -1049,6 +1066,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<T, U> {
+ foo: T,
+ bar: U,
+}
+"#,
+ r#"
+struct Foo<T, U> {
+ foo: T,
+ bar: U,
+}
+
+impl<T, U> Default for Foo<T, U> {
+ $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: Clone>(T, usize);
+"#,
+ r#"
+struct Foo<T: Clone>(T, usize);
+
+impl<T: Clone> Clone for Foo<T> {
+ $0fn clone(&self) -> Self {
+ Self(self.0.clone(), self.1.clone())
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
fn test_ignore_derive_macro_without_input() {
check_assist_not_applicable(
replace_derive_with_manual_impl,
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index ed69973af9..e1938307cf 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::GenericParamList>,
+) -> 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 {