From 1fae96a8d4fb452216906f8909d421ad884fd929 Mon Sep 17 00:00:00 2001 From: Jess Balint Date: Fri, 22 May 2020 08:51:37 -0500 Subject: handle the case of conflicting lifetime param name - and clean/format code --- .../src/handlers/change_lifetime_anon_to_named.rs | 43 ++++++++++++++++++---- 1 file 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 @@ use crate::{AssistContext, AssistId, Assists}; -use ra_syntax::{ast, ast::{TypeParamsOwner}, AstNode, SyntaxKind}; +use ra_syntax::{ast, ast::TypeParamsOwner, AstNode, SyntaxKind}; +use std::collections::HashSet; /// Assist: change_lifetime_anon_to_named /// @@ -24,7 +25,7 @@ use ra_syntax::{ast, ast::{TypeParamsOwner}, AstNode, SyntaxKind}; /// } /// } /// ``` -// TODO : How can we handle renaming any one of multiple anonymous lifetimes? +// FIXME: How can we handle renaming any one of multiple anonymous lifetimes? pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let lifetime_token = ctx.find_token_at_offset(SyntaxKind::LIFETIME)?; 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 if impl_kw.kind() != SyntaxKind::IMPL_KW { return None; } + let new_lifetime_param = match impl_def.type_param_list() { + Some(type_params) => { + let used_lifetime_params: HashSet<_> = type_params + .lifetime_params() + .map(|p| { + let mut param_name = p.syntax().text().to_string(); + param_name.remove(0); + param_name + }) + .collect(); + "abcdefghijklmnopqrstuvwxyz" + .chars() + .find(|c| !used_lifetime_params.contains(&c.to_string()))? + } + None => 'a', + }; acc.add( AssistId("change_lifetime_anon_to_named"), "Give anonymous lifetime a name", @@ -52,17 +69,20 @@ pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistConte Some(type_params) => { builder.insert( (u32::from(type_params.syntax().text_range().end()) - 1).into(), - ", 'a", + format!(", '{}", new_lifetime_param), ); - }, + } None => { builder.insert( impl_kw.text_range().end(), - "<'a>", + format!("<'{}>", new_lifetime_param), ); - }, + } } - builder.replace(lifetime_arg.syntax().text_range(), "'a"); + builder.replace( + lifetime_arg.syntax().text_range(), + format!("'{}", new_lifetime_param), + ); }, ) } @@ -120,4 +140,13 @@ mod tests { r#"impl Cursor"#, ); } + + #[test] + fn test_with_existing_lifetime_name_conflict() { + check_assist( + change_lifetime_anon_to_named, + r#"impl<'a, 'b> Cursor<'a, 'b, '_<|>>"#, + r#"impl<'a, 'b, 'c> Cursor<'a, 'b, 'c>"#, + ); + } } -- cgit v1.2.3