about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ide-assists/src/handlers/introduce_named_generic.rs2
-rw-r--r--crates/ide-assists/src/utils/suggest_name.rs72
2 files changed, 44 insertions, 30 deletions
diff --git a/crates/ide-assists/src/handlers/introduce_named_generic.rs b/crates/ide-assists/src/handlers/introduce_named_generic.rs
index abbdc5aee95..b1daa7802ed 100644
--- a/crates/ide-assists/src/handlers/introduce_named_generic.rs
+++ b/crates/ide-assists/src/handlers/introduce_named_generic.rs
@@ -33,7 +33,7 @@ pub(crate) fn introduce_named_generic(acc: &mut Assists, ctx: &AssistContext<'_>
             let fn_ = edit.make_mut(fn_);
             let fn_generic_param_list = fn_.get_or_create_generic_param_list();
             let type_param_name =
-                suggest_name::for_generic_parameter(&impl_trait_type, &fn_generic_param_list);
+                suggest_name::for_impl_trait_as_generic(&impl_trait_type, &fn_generic_param_list);
 
             let type_param = make::type_param(make::name(&type_param_name), Some(type_bound_list))
                 .clone_for_update();
diff --git a/crates/ide-assists/src/utils/suggest_name.rs b/crates/ide-assists/src/utils/suggest_name.rs
index ae3fd30b65c..8a698e4068a 100644
--- a/crates/ide-assists/src/utils/suggest_name.rs
+++ b/crates/ide-assists/src/utils/suggest_name.rs
@@ -58,7 +58,48 @@ const USELESS_METHODS: &[&str] = &[
     "into_future",
 ];
 
-pub(crate) fn for_generic_parameter(
+/// Suggest a unique name for generic parameter.
+///
+/// `existing_params` is used to check if the name conflicts with existing
+/// generic parameters.
+///
+/// The function checks if the name conflicts with existing generic parameters.
+/// If so, it will try to resolve the conflict by adding a number suffix, e.g.
+/// `T`, `T0`, `T1`, ...
+pub(crate) fn for_unique_generic_name(
+    name: &str,
+    existing_params: &ast::GenericParamList,
+) -> SmolStr {
+    let param_names = existing_params.generic_params().map(|param| param.to_string()).collect_vec();
+
+    let mut name = name.to_string();
+    let base_len = name.len();
+    // 4*len bytes for base, and 2 bytes for 2 digits
+    name.reserve(4 * base_len + 2);
+
+    let mut count = 0;
+    while param_names.contains(&name) {
+        name.truncate(base_len);
+        name.push_str(&count.to_string());
+        count += 1;
+    }
+
+    name.into()
+}
+
+/// Suggest name of impl trait type
+///
+/// `existing_params` is used to check if the name conflicts with existing
+/// generic parameters.
+///
+/// # Current implementation
+///
+/// In current implementation, the function tries to get the name from the first
+/// character of the name for the first type bound.
+///
+/// If the name conflicts with existing generic parameters, it will try to
+/// resolve the conflict with `for_unique_generic_name`.
+pub(crate) fn for_impl_trait_as_generic(
     ty: &ast::ImplTraitType,
     existing_params: &ast::GenericParamList,
 ) -> SmolStr {
@@ -67,34 +108,7 @@ pub(crate) fn for_generic_parameter(
         .and_then(|bounds| bounds.syntax().text().char_at(0.into()))
         .unwrap_or('T');
 
-    // let existing_params = existing_params.generic_params();
-    let conflict = existing_params
-        .generic_params()
-        .filter(|param| {
-            param.syntax().text_range().len() == 1.into()
-                && param.syntax().text().char_at(0.into()).unwrap() == c
-        })
-        .count()
-        > 0;
-
-    let buffer = &mut [0; 4];
-    if conflict {
-        let mut name = String::from(c.encode_utf8(buffer));
-        name.reserve(6); // 4B for c, and 2B for 2 digits
-        let base_len = name.len();
-        let mut count = 0;
-        loop {
-            name.truncate(base_len);
-            name.push_str(&count.to_string());
-            if existing_params.generic_params().all(|param| param.to_string() != name) {
-                break;
-            }
-            count += 1;
-        }
-        SmolStr::from(name)
-    } else {
-        c.encode_utf8(buffer).into()
-    }
+    for_unique_generic_name(c.encode_utf8(&mut [0; 4]), existing_params)
 }
 
 /// Suggest name of variable for given expression