diff --git a/crates/ide-assists/src/handlers/flip_binexpr.rs b/crates/ide-assists/src/handlers/flip_binexpr.rs index 247e8109abc9..8f2306e9037e 100644 --- a/crates/ide-assists/src/handlers/flip_binexpr.rs +++ b/crates/ide-assists/src/handlers/flip_binexpr.rs @@ -1,6 +1,7 @@ use syntax::{ SyntaxKind, T, - ast::{self, AstNode, BinExpr, syntax_factory::SyntaxFactory}, + ast::{self, AstNode, BinExpr, RangeItem, syntax_factory::SyntaxFactory}, + syntax_editor::Position, }; use crate::{AssistContext, AssistId, Assists}; @@ -87,6 +88,74 @@ impl From for FlipAction { } } +// Assist: flip_range_expr +// +// Flips operands of a range expression. +// +// ``` +// fn main() { +// let _ = 90..$02; +// } +// ``` +// -> +// ``` +// fn main() { +// let _ = 2..90; +// } +// ``` +// --- +// ``` +// fn main() { +// let _ = 90..$0; +// } +// ``` +// -> +// ``` +// fn main() { +// let _ = ..90; +// } +// ``` +pub(crate) fn flip_range_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let range_expr = ctx.find_node_at_offset::()?; + let op = range_expr.op_token()?; + let start = range_expr.start(); + let end = range_expr.end(); + + if !op.text_range().contains_range(ctx.selection_trimmed()) { + return None; + } + if start.is_none() && end.is_none() { + return None; + } + + acc.add( + AssistId::refactor_rewrite("flip_range_expr"), + "Flip range expression", + op.text_range(), + |builder| { + let mut edit = builder.make_editor(range_expr.syntax()); + + match (start, end) { + (Some(start), Some(end)) => { + edit.replace(start.syntax(), end.syntax()); + edit.replace(end.syntax(), start.syntax()); + } + (Some(start), None) => { + edit.delete(start.syntax()); + edit.insert(Position::after(&op), start.syntax().clone_for_update()); + } + (None, Some(end)) => { + edit.delete(end.syntax()); + edit.insert(Position::before(&op), end.syntax().clone_for_update()); + } + (None, None) => (), + } + + builder.add_file_edits(ctx.vfs_file_id(), edit); + }, + ) +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index 4682c0473238..0e160af652f9 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -283,6 +283,7 @@ mod handlers { extract_type_alias::extract_type_alias, fix_visibility::fix_visibility, flip_binexpr::flip_binexpr, + flip_binexpr::flip_range_expr, flip_comma::flip_comma, flip_or_pattern::flip_or_pattern, flip_trait_bound::flip_trait_bound, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 91348be97eb7..7b042ed4dc99 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -1298,6 +1298,40 @@ fn foo() { ) } +#[test] +fn doctest_flip_range_expr() { + check_doc_test( + "flip_range_expr", + r#####" +fn main() { + let _ = 90..$02; +} +"#####, + r#####" +fn main() { + let _ = 2..90; +} +"#####, + ) +} + +#[test] +fn doctest_flip_range_expr_1() { + check_doc_test( + "flip_range_expr", + r#####" +fn main() { + let _ = 90..$0; +} +"#####, + r#####" +fn main() { + let _ = ..90; +} +"#####, + ) +} + #[test] fn doctest_flip_trait_bound() { check_doc_test(