aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists')
-rw-r--r--crates/ra_assists/src/handlers/change_lifetime_anon_to_named.rs43
1 files changed, 36 insertions, 7 deletions
diff --git a/crates/ra_assists/src/handlers/change_lifetime_anon_to_named.rs b/crates/ra_assists/src/handlers/change_lifetime_anon_to_named.rs
index 63f0a7dab..8d8f7833f 100644
--- a/crates/ra_assists/src/handlers/change_lifetime_anon_to_named.rs
+++ b/crates/ra_assists/src/handlers/change_lifetime_anon_to_named.rs
@@ -1,5 +1,6 @@
1use crate::{AssistContext, AssistId, Assists}; 1use crate::{AssistContext, AssistId, Assists};
2use ra_syntax::{ast, ast::{TypeParamsOwner}, AstNode, SyntaxKind}; 2use ra_syntax::{ast, ast::TypeParamsOwner, AstNode, SyntaxKind};
3use std::collections::HashSet;
3 4
4/// Assist: change_lifetime_anon_to_named 5/// Assist: change_lifetime_anon_to_named
5/// 6///
@@ -24,7 +25,7 @@ use ra_syntax::{ast, ast::{TypeParamsOwner}, AstNode, SyntaxKind};
24/// } 25/// }
25/// } 26/// }
26/// ``` 27/// ```
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?
28pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 29pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
29 let lifetime_token = ctx.find_token_at_offset(SyntaxKind::LIFETIME)?; 30 let lifetime_token = ctx.find_token_at_offset(SyntaxKind::LIFETIME)?;
30 let lifetime_arg = ast::LifetimeArg::cast(lifetime_token.parent())?; 31 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
43 if impl_kw.kind() != SyntaxKind::IMPL_KW { 44 if impl_kw.kind() != SyntaxKind::IMPL_KW {
44 return None; 45 return None;
45 } 46 }
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 };
46 acc.add( 63 acc.add(
47 AssistId("change_lifetime_anon_to_named"), 64 AssistId("change_lifetime_anon_to_named"),
48 "Give anonymous lifetime a name", 65 "Give anonymous lifetime a name",
@@ -52,17 +69,20 @@ pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistConte
52 Some(type_params) => { 69 Some(type_params) => {
53 builder.insert( 70 builder.insert(
54 (u32::from(type_params.syntax().text_range().end()) - 1).into(), 71 (u32::from(type_params.syntax().text_range().end()) - 1).into(),
55 ", 'a", 72 format!(", '{}", new_lifetime_param),
56 ); 73 );
57 }, 74 }
58 None => { 75 None => {
59 builder.insert( 76 builder.insert(
60 impl_kw.text_range().end(), 77 impl_kw.text_range().end(),
61 "<'a>", 78 format!("<'{}>", new_lifetime_param),
62 ); 79 );
63 }, 80 }
64 } 81 }
65 builder.replace(lifetime_arg.syntax().text_range(), "'a"); 82 builder.replace(
83 lifetime_arg.syntax().text_range(),
84 format!("'{}", new_lifetime_param),
85 );
66 }, 86 },
67 ) 87 )
68 } 88 }
@@ -120,4 +140,13 @@ mod tests {
120 r#"impl<T, 'a> Cursor<T, 'a>"#, 140 r#"impl<T, 'a> Cursor<T, 'a>"#,
121 ); 141 );
122 } 142 }
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 }
123} 152}