mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
parent
90332ca219
commit
2ab79c6f4d
3 changed files with 149 additions and 0 deletions
123
crates/ra_assists/src/handlers/change_lifetime_anon_to_named.rs
Normal file
123
crates/ra_assists/src/handlers/change_lifetime_anon_to_named.rs
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
use crate::{AssistContext, AssistId, Assists};
|
||||||
|
use ra_syntax::{ast, ast::{TypeParamsOwner}, AstNode, SyntaxKind};
|
||||||
|
|
||||||
|
/// Assist: change_lifetime_anon_to_named
|
||||||
|
///
|
||||||
|
/// Change an anonymous lifetime to a named lifetime.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// impl Cursor<'_<|>> {
|
||||||
|
/// fn node(self) -> &SyntaxNode {
|
||||||
|
/// match self {
|
||||||
|
/// Cursor::Replace(node) | Cursor::Before(node) => node,
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// ->
|
||||||
|
/// ```
|
||||||
|
/// impl<'a> Cursor<'a> {
|
||||||
|
/// fn node(self) -> &SyntaxNode {
|
||||||
|
/// match self {
|
||||||
|
/// Cursor::Replace(node) | Cursor::Before(node) => node,
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
// TODO : 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())?;
|
||||||
|
if lifetime_arg.syntax().text() != "'_" {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let next_token = lifetime_token.next_token()?;
|
||||||
|
if next_token.kind() != SyntaxKind::R_ANGLE {
|
||||||
|
// only allow naming the last anonymous lifetime
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
match lifetime_arg.syntax().ancestors().find_map(ast::ImplDef::cast) {
|
||||||
|
Some(impl_def) => {
|
||||||
|
// get the `impl` keyword so we know where to add the lifetime argument
|
||||||
|
let impl_kw = impl_def.syntax().first_child_or_token()?.into_token()?;
|
||||||
|
if impl_kw.kind() != SyntaxKind::IMPL_KW {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
acc.add(
|
||||||
|
AssistId("change_lifetime_anon_to_named"),
|
||||||
|
"Give anonymous lifetime a name",
|
||||||
|
lifetime_arg.syntax().text_range(),
|
||||||
|
|builder| {
|
||||||
|
match impl_def.type_param_list() {
|
||||||
|
Some(type_params) => {
|
||||||
|
builder.insert(
|
||||||
|
(u32::from(type_params.syntax().text_range().end()) - 1).into(),
|
||||||
|
", 'a",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
builder.insert(
|
||||||
|
impl_kw.text_range().end(),
|
||||||
|
"<'a>",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
builder.replace(lifetime_arg.syntax().text_range(), "'a");
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_example_case() {
|
||||||
|
check_assist(
|
||||||
|
change_lifetime_anon_to_named,
|
||||||
|
r#"impl Cursor<'_<|>> {
|
||||||
|
fn node(self) -> &SyntaxNode {
|
||||||
|
match self {
|
||||||
|
Cursor::Replace(node) | Cursor::Before(node) => node,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"#,
|
||||||
|
r#"impl<'a> Cursor<'a> {
|
||||||
|
fn node(self) -> &SyntaxNode {
|
||||||
|
match self {
|
||||||
|
Cursor::Replace(node) | Cursor::Before(node) => node,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_example_case_simplified() {
|
||||||
|
check_assist(
|
||||||
|
change_lifetime_anon_to_named,
|
||||||
|
r#"impl Cursor<'_<|>> {"#,
|
||||||
|
r#"impl<'a> Cursor<'a> {"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_not_applicable() {
|
||||||
|
check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<'_><|> {"#);
|
||||||
|
check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<|><'_> {"#);
|
||||||
|
check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<'a<|>> {"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_with_type_parameter() {
|
||||||
|
check_assist(
|
||||||
|
change_lifetime_anon_to_named,
|
||||||
|
r#"impl<T> Cursor<T, '_<|>>"#,
|
||||||
|
r#"impl<T, 'a> Cursor<T, 'a>"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -112,6 +112,7 @@ mod handlers {
|
||||||
mod add_turbo_fish;
|
mod add_turbo_fish;
|
||||||
mod apply_demorgan;
|
mod apply_demorgan;
|
||||||
mod auto_import;
|
mod auto_import;
|
||||||
|
mod change_lifetime_anon_to_named;
|
||||||
mod change_return_type_to_result;
|
mod change_return_type_to_result;
|
||||||
mod change_visibility;
|
mod change_visibility;
|
||||||
mod early_return;
|
mod early_return;
|
||||||
|
@ -151,6 +152,7 @@ mod handlers {
|
||||||
add_turbo_fish::add_turbo_fish,
|
add_turbo_fish::add_turbo_fish,
|
||||||
apply_demorgan::apply_demorgan,
|
apply_demorgan::apply_demorgan,
|
||||||
auto_import::auto_import,
|
auto_import::auto_import,
|
||||||
|
change_lifetime_anon_to_named::change_lifetime_anon_to_named,
|
||||||
change_return_type_to_result::change_return_type_to_result,
|
change_return_type_to_result::change_return_type_to_result,
|
||||||
change_visibility::change_visibility,
|
change_visibility::change_visibility,
|
||||||
early_return::convert_to_guarded_return,
|
early_return::convert_to_guarded_return,
|
||||||
|
|
|
@ -259,6 +259,30 @@ fn main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `change_lifetime_anon_to_named`
|
||||||
|
|
||||||
|
Change an anonymous lifetime to a named lifetime.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// BEFORE
|
||||||
|
impl Cursor<'_<|>> {
|
||||||
|
fn node(self) -> &SyntaxNode {
|
||||||
|
match self {
|
||||||
|
Cursor::Replace(node) | Cursor::Before(node) => node,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AFTER
|
||||||
|
impl<'a> Cursor<'a> {
|
||||||
|
fn node(self) -> &SyntaxNode {
|
||||||
|
match self {
|
||||||
|
Cursor::Replace(node) | Cursor::Before(node) => node,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## `change_return_type_to_result`
|
## `change_return_type_to_result`
|
||||||
|
|
||||||
Change the function's return type to Result.
|
Change the function's return type to Result.
|
||||||
|
|
Loading…
Reference in a new issue