Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/generate_delegate_trait.rs')
| -rw-r--r-- | crates/ide-assists/src/handlers/generate_delegate_trait.rs | 81 |
1 files changed, 66 insertions, 15 deletions
diff --git a/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/crates/ide-assists/src/handlers/generate_delegate_trait.rs index bf4ce5c907..66bf9b0186 100644 --- a/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -2,13 +2,14 @@ use std::ops::Not; use crate::{ assist_context::{AssistContext, Assists}, - utils::{convert_param_list_to_arg_list, suggest_name}, + utils::convert_param_list_to_arg_list, }; use either::Either; use hir::{db::HirDatabase, HasVisibility}; use ide_db::{ assists::{AssistId, GroupLabel}, path_transform::PathTransform, + syntax_helpers::suggest_name, FxHashMap, FxHashSet, }; use itertools::Itertools; @@ -281,8 +282,11 @@ fn generate_impl( ai.assoc_items() .filter(|item| matches!(item, AssocItem::MacroCall(_)).not()) .for_each(|item| { - let assoc = - process_assoc_item(item, qualified_path_type.clone(), field_name); + let assoc = process_assoc_item( + item.clone_for_update(), + qualified_path_type.clone(), + field_name, + ); if let Some(assoc) = assoc { delegate_assoc_items.add_item(assoc); } @@ -583,7 +587,7 @@ fn resolve_name_conflicts( for old_strukt_param in old_strukt_params.generic_params() { // Get old name from `strukt` - let mut name = SmolStr::from(match &old_strukt_param { + let name = SmolStr::from(match &old_strukt_param { ast::GenericParam::ConstParam(c) => c.name()?.to_string(), ast::GenericParam::LifetimeParam(l) => { l.lifetime()?.lifetime_ident_token()?.to_string() @@ -592,8 +596,19 @@ fn resolve_name_conflicts( }); // The new name cannot be conflicted with generics in trait, and the renamed names. - name = suggest_name::for_unique_generic_name(&name, old_impl_params); - name = suggest_name::for_unique_generic_name(&name, ¶ms); + let param_list_to_names = |param_list: &GenericParamList| { + param_list.generic_params().flat_map(|param| match param { + ast::GenericParam::TypeParam(t) => t.name().map(|name| name.to_string()), + p => Some(p.to_string()), + }) + }; + let existing_names = param_list_to_names(old_impl_params) + .chain(param_list_to_names(¶ms)) + .collect_vec(); + let mut name_generator = suggest_name::NameGenerator::new_with_names( + existing_names.iter().map(|s| s.as_str()), + ); + let name = name_generator.suggest_name(&name); match old_strukt_param { ast::GenericParam::ConstParam(c) => { if let Some(const_ty) = c.ty() { @@ -1212,9 +1227,9 @@ struct S<T> { b : B<T>, } -impl<T0> Trait<T0> for S<T0> { - fn f(&self, a: T0) -> T0 { - <B<T0> as Trait<T0>>::f(&self.b, a) +impl<T1> Trait<T1> for S<T1> { + fn f(&self, a: T1) -> T1 { + <B<T1> as Trait<T1>>::f(&self.b, a) } } "#, @@ -1526,12 +1541,12 @@ where b : B<T, T1>, } -impl<T, T2, T10> Trait<T> for S<T2, T10> +impl<T, T2, T3> Trait<T> for S<T2, T3> where - T10: AnotherTrait + T3: AnotherTrait { fn f(&self, a: T) -> T { - <B<T2, T10> as Trait<T>>::f(&self.b, a) + <B<T2, T3> as Trait<T>>::f(&self.b, a) } }"#, ); @@ -1588,12 +1603,12 @@ where b : B<T>, } -impl<T, T0> Trait<T> for S<T0> +impl<T, T2> Trait<T> for S<T2> where - T0: AnotherTrait + T2: AnotherTrait { fn f(&self, a: T) -> T { - <B<T0> as Trait<T>>::f(&self.b, a) + <B<T2> as Trait<T>>::f(&self.b, a) } }"#, ); @@ -1785,4 +1800,40 @@ impl T for B { "#, ); } + + #[test] + fn assoc_items_attributes_mutably_cloned() { + check_assist( + generate_delegate_trait, + r#" +pub struct A; +pub trait C<D> { + #[allow(clippy::dead_code)] + fn a_funk(&self) -> &D; +} + +pub struct B<T: C<A>> { + has_dr$0ain: T, +} +"#, + r#" +pub struct A; +pub trait C<D> { + #[allow(clippy::dead_code)] + fn a_funk(&self) -> &D; +} + +pub struct B<T: C<A>> { + has_drain: T, +} + +impl<D, T: C<A>> C<D> for B<T> { + #[allow(clippy::dead_code)] + fn a_funk(&self) -> &D { + <T as C<D>>::a_funk(&self.has_drain) + } +} +"#, + ) + } } |