Skip to content

Commit 1fae96a

Browse files
committed
handle the case of conflicting lifetime param name
- and clean/format code
1 parent 2ab79c6 commit 1fae96a

File tree

1 file changed

+36
-7
lines changed

1 file changed

+36
-7
lines changed

crates/ra_assists/src/handlers/change_lifetime_anon_to_named.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::{AssistContext, AssistId, Assists};
2-
use ra_syntax::{ast, ast::{TypeParamsOwner}, AstNode, SyntaxKind};
2+
use ra_syntax::{ast, ast::TypeParamsOwner, AstNode, SyntaxKind};
3+
use std::collections::HashSet;
34

45
/// Assist: change_lifetime_anon_to_named
56
///
@@ -24,7 +25,7 @@ use ra_syntax::{ast, ast::{TypeParamsOwner}, AstNode, SyntaxKind};
2425
/// }
2526
/// }
2627
/// ```
27-
// TODO : How can we handle renaming any one of multiple anonymous lifetimes?
28+
// FIXME: How can we handle renaming any one of multiple anonymous lifetimes?
2829
pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
2930
let lifetime_token = ctx.find_token_at_offset(SyntaxKind::LIFETIME)?;
3031
let lifetime_arg = ast::LifetimeArg::cast(lifetime_token.parent())?;
@@ -43,6 +44,22 @@ pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistConte
4344
if impl_kw.kind() != SyntaxKind::IMPL_KW {
4445
return None;
4546
}
47+
let new_lifetime_param = match impl_def.type_param_list() {
48+
Some(type_params) => {
49+
let used_lifetime_params: HashSet<_> = type_params
50+
.lifetime_params()
51+
.map(|p| {
52+
let mut param_name = p.syntax().text().to_string();
53+
param_name.remove(0);
54+
param_name
55+
})
56+
.collect();
57+
"abcdefghijklmnopqrstuvwxyz"
58+
.chars()
59+
.find(|c| !used_lifetime_params.contains(&c.to_string()))?
60+
}
61+
None => 'a',
62+
};
4663
acc.add(
4764
AssistId("change_lifetime_anon_to_named"),
4865
"Give anonymous lifetime a name",
@@ -52,17 +69,20 @@ pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistConte
5269
Some(type_params) => {
5370
builder.insert(
5471
(u32::from(type_params.syntax().text_range().end()) - 1).into(),
55-
", 'a",
72+
format!(", '{}", new_lifetime_param),
5673
);
57-
},
74+
}
5875
None => {
5976
builder.insert(
6077
impl_kw.text_range().end(),
61-
"<'a>",
78+
format!("<'{}>", new_lifetime_param),
6279
);
63-
},
80+
}
6481
}
65-
builder.replace(lifetime_arg.syntax().text_range(), "'a");
82+
builder.replace(
83+
lifetime_arg.syntax().text_range(),
84+
format!("'{}", new_lifetime_param),
85+
);
6686
},
6787
)
6888
}
@@ -120,4 +140,13 @@ mod tests {
120140
r#"impl<T, 'a> Cursor<T, 'a>"#,
121141
);
122142
}
143+
144+
#[test]
145+
fn test_with_existing_lifetime_name_conflict() {
146+
check_assist(
147+
change_lifetime_anon_to_named,
148+
r#"impl<'a, 'b> Cursor<'a, 'b, '_<|>>"#,
149+
r#"impl<'a, 'b, 'c> Cursor<'a, 'b, 'c>"#,
150+
);
151+
}
123152
}

0 commit comments

Comments
 (0)