Skip to content

Commit 186553d

Browse files
committed
refactor: extracted the fn handling conflicts in generics and add docs
* Extracted the function `for_unique_generic_name` that handling generics with identical names for reusability. * Renamed `for_generic_params` to `for_impl_trait_as_generic` for clarity * Added documentations for `for_impl_trait_as_generic` and `for_unique_generic_name`
1 parent e8dc8cc commit 186553d

File tree

2 files changed

+44
-30
lines changed

2 files changed

+44
-30
lines changed

crates/ide-assists/src/handlers/introduce_named_generic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub(crate) fn introduce_named_generic(acc: &mut Assists, ctx: &AssistContext<'_>
3333
let fn_ = edit.make_mut(fn_);
3434
let fn_generic_param_list = fn_.get_or_create_generic_param_list();
3535
let type_param_name =
36-
suggest_name::for_generic_parameter(&impl_trait_type, &fn_generic_param_list);
36+
suggest_name::for_impl_trait_as_generic(&impl_trait_type, &fn_generic_param_list);
3737

3838
let type_param = make::type_param(make::name(&type_param_name), Some(type_bound_list))
3939
.clone_for_update();

crates/ide-assists/src/utils/suggest_name.rs

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,48 @@ const USELESS_METHODS: &[&str] = &[
5858
"into_future",
5959
];
6060

61-
pub(crate) fn for_generic_parameter(
61+
/// Suggest a unique name for generic parameter.
62+
///
63+
/// `existing_params` is used to check if the name conflicts with existing
64+
/// generic parameters.
65+
///
66+
/// The function checks if the name conflicts with existing generic parameters.
67+
/// If so, it will try to resolve the conflict by adding a number suffix, e.g.
68+
/// `T`, `T0`, `T1`, ...
69+
pub(crate) fn for_unique_generic_name(
70+
name: &str,
71+
existing_params: &ast::GenericParamList,
72+
) -> SmolStr {
73+
let param_names = existing_params.generic_params().map(|param| param.to_string()).collect_vec();
74+
75+
let mut name = name.to_string();
76+
let base_len = name.len();
77+
// 4*len bytes for base, and 2 bytes for 2 digits
78+
name.reserve(4 * base_len + 2);
79+
80+
let mut count = 0;
81+
while param_names.contains(&name) {
82+
name.truncate(base_len);
83+
name.push_str(&count.to_string());
84+
count += 1;
85+
}
86+
87+
name.into()
88+
}
89+
90+
/// Suggest name of impl trait type
91+
///
92+
/// `existing_params` is used to check if the name conflicts with existing
93+
/// generic parameters.
94+
///
95+
/// # Current implementation
96+
///
97+
/// In current implementation, the function tries to get the name from the first
98+
/// character of the name for the first type bound.
99+
///
100+
/// If the name conflicts with existing generic parameters, it will try to
101+
/// resolve the conflict with `for_unique_generic_name`.
102+
pub(crate) fn for_impl_trait_as_generic(
62103
ty: &ast::ImplTraitType,
63104
existing_params: &ast::GenericParamList,
64105
) -> SmolStr {
@@ -67,34 +108,7 @@ pub(crate) fn for_generic_parameter(
67108
.and_then(|bounds| bounds.syntax().text().char_at(0.into()))
68109
.unwrap_or('T');
69110

70-
// let existing_params = existing_params.generic_params();
71-
let conflict = existing_params
72-
.generic_params()
73-
.filter(|param| {
74-
param.syntax().text_range().len() == 1.into()
75-
&& param.syntax().text().char_at(0.into()).unwrap() == c
76-
})
77-
.count()
78-
> 0;
79-
80-
let buffer = &mut [0; 4];
81-
if conflict {
82-
let mut name = String::from(c.encode_utf8(buffer));
83-
name.reserve(6); // 4B for c, and 2B for 2 digits
84-
let base_len = name.len();
85-
let mut count = 0;
86-
loop {
87-
name.truncate(base_len);
88-
name.push_str(&count.to_string());
89-
if existing_params.generic_params().all(|param| param.to_string() != name) {
90-
break;
91-
}
92-
count += 1;
93-
}
94-
SmolStr::from(name)
95-
} else {
96-
c.encode_utf8(buffer).into()
97-
}
111+
for_unique_generic_name(c.encode_utf8(&mut [0; 4]), existing_params)
98112
}
99113

100114
/// Suggest name of variable for given expression

0 commit comments

Comments
 (0)