Skip to content

Commit e8dc8cc

Browse files
committed
fix: pick up new names when the name exists in 'introduce_named_generic'
1 parent 34df296 commit e8dc8cc

File tree

2 files changed

+45
-32
lines changed

2 files changed

+45
-32
lines changed

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,16 @@ pub(crate) fn introduce_named_generic(acc: &mut Assists, ctx: &AssistContext<'_>
3131
|edit| {
3232
let impl_trait_type = edit.make_mut(impl_trait_type);
3333
let fn_ = edit.make_mut(fn_);
34-
35-
let type_param_name = suggest_name::for_generic_parameter(&impl_trait_type);
34+
let fn_generic_param_list = fn_.get_or_create_generic_param_list();
35+
let type_param_name =
36+
suggest_name::for_generic_parameter(&impl_trait_type, &fn_generic_param_list);
3637

3738
let type_param = make::type_param(make::name(&type_param_name), Some(type_bound_list))
3839
.clone_for_update();
3940
let new_ty = make::ty(&type_param_name).clone_for_update();
4041

4142
ted::replace(impl_trait_type.syntax(), new_ty.syntax());
42-
fn_.get_or_create_generic_param_list().add_generic_param(type_param.into());
43+
fn_generic_param_list.add_generic_param(type_param.into());
4344

4445
if let Some(cap) = ctx.config.snippet_cap {
4546
if let Some(generic_param) =
@@ -111,12 +112,19 @@ fn foo<$0B: Bar
111112

112113
#[test]
113114
fn replace_impl_trait_with_exist_generic_letter() {
114-
// FIXME: This is wrong, we should pick a different name if the one we
115-
// want is already bound.
116115
check_assist(
117116
introduce_named_generic,
118117
r#"fn foo<B>(bar: $0impl Bar) {}"#,
119-
r#"fn foo<B, $0B: Bar>(bar: B) {}"#,
118+
r#"fn foo<B, $0B0: Bar>(bar: B0) {}"#,
119+
);
120+
}
121+
122+
#[test]
123+
fn replace_impl_trait_with_more_exist_generic_letter() {
124+
check_assist(
125+
introduce_named_generic,
126+
r#"fn foo<B, B0, B1, B3>(bar: $0impl Bar) {}"#,
127+
r#"fn foo<B, B0, B1, B3, $0B2: Bar>(bar: B2) {}"#,
120128
);
121129
}
122130

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

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

61-
pub(crate) fn for_unique_generic_name(
62-
name: &str,
61+
pub(crate) fn for_generic_parameter(
62+
ty: &ast::ImplTraitType,
6363
existing_params: &ast::GenericParamList,
6464
) -> SmolStr {
65-
let param_names = existing_params
66-
.generic_params()
67-
.map(|param| match param {
68-
ast::GenericParam::TypeParam(t) => t.name().unwrap().to_string(),
69-
p => p.to_string(),
70-
})
71-
.collect_vec();
72-
let mut name = name.to_string();
73-
let base_len = name.len();
74-
// 4*len bytes for base, and 2 bytes for 2 digits
75-
name.reserve(4 * base_len + 2);
76-
77-
let mut count = 0;
78-
while param_names.contains(&name) {
79-
name.truncate(base_len);
80-
name.push_str(&count.to_string());
81-
count += 1;
82-
}
83-
84-
name.into()
85-
}
86-
87-
pub(crate) fn for_generic_parameter(ty: &ast::ImplTraitType) -> SmolStr {
8865
let c = ty
8966
.type_bound_list()
9067
.and_then(|bounds| bounds.syntax().text().char_at(0.into()))
9168
.unwrap_or('T');
92-
c.encode_utf8(&mut [0; 4]).into()
69+
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+
}
9398
}
9499

95100
/// Suggest name of variable for given expression

0 commit comments

Comments
 (0)