about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-01-09 11:59:09 +0100
committerLukas Wirth <lukastw97@gmail.com>2023-01-09 11:59:17 +0100
commit0dd26821783ccc809fb0995f178fd6c53f6eebd7 (patch)
treee166f125ecad91c83937c8db6d5015b2c7cbd0be
parent3dd2f99c49d225b08e38ccd1981e1adef8fd2901 (diff)
downloadrust-0dd26821783ccc809fb0995f178fd6c53f6eebd7.tar.gz
rust-0dd26821783ccc809fb0995f178fd6c53f6eebd7.zip
Refactor replace_arith assists into one module
-rw-r--r--crates/ide-assists/src/handlers/replace_arith_op.rs226
-rw-r--r--crates/ide-assists/src/handlers/replace_arith_with_checked.rs45
-rw-r--r--crates/ide-assists/src/handlers/replace_arith_with_saturating.rs48
-rw-r--r--crates/ide-assists/src/handlers/replace_arith_with_wrapping.rs48
-rw-r--r--crates/ide-assists/src/lib.rs10
-rw-r--r--crates/ide-assists/src/utils.rs124
6 files changed, 234 insertions, 267 deletions
diff --git a/crates/ide-assists/src/handlers/replace_arith_op.rs b/crates/ide-assists/src/handlers/replace_arith_op.rs
new file mode 100644
index 00000000000..f1ca35cafc3
--- /dev/null
+++ b/crates/ide-assists/src/handlers/replace_arith_op.rs
@@ -0,0 +1,226 @@
+use ide_db::assists::{AssistId, AssistKind, GroupLabel};
+use syntax::{
+    ast::{self, ArithOp, BinaryOp},
+    AstNode, TextRange,
+};
+
+use crate::assist_context::{AssistContext, Assists};
+
+// Assist: replace_arith_with_checked
+//
+// Replaces arithmetic on integers with the `checked_*` equivalent.
+//
+// ```
+// fn main() {
+//   let x = 1 $0+ 2;
+// }
+// ```
+// ->
+// ```
+// fn main() {
+//   let x = 1.checked_add(2);
+// }
+// ```
+pub(crate) fn replace_arith_with_checked(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+    replace_arith(acc, ctx, ArithKind::Checked)
+}
+
+// Assist: replace_arith_with_saturating
+//
+// Replaces arithmetic on integers with the `saturating_*` equivalent.
+//
+// ```
+// fn main() {
+//   let x = 1 $0+ 2;
+// }
+// ```
+// ->
+// ```
+// fn main() {
+//   let x = 1.saturating_add(2);
+// }
+// ```
+pub(crate) fn replace_arith_with_saturating(
+    acc: &mut Assists,
+    ctx: &AssistContext<'_>,
+) -> Option<()> {
+    replace_arith(acc, ctx, ArithKind::Saturating)
+}
+
+// Assist: replace_arith_with_wrapping
+//
+// Replaces arithmetic on integers with the `wrapping_*` equivalent.
+//
+// ```
+// fn main() {
+//   let x = 1 $0+ 2;
+// }
+// ```
+// ->
+// ```
+// fn main() {
+//   let x = 1.wrapping_add(2);
+// }
+// ```
+pub(crate) fn replace_arith_with_wrapping(
+    acc: &mut Assists,
+    ctx: &AssistContext<'_>,
+) -> Option<()> {
+    replace_arith(acc, ctx, ArithKind::Wrapping)
+}
+
+fn replace_arith(acc: &mut Assists, ctx: &AssistContext<'_>, kind: ArithKind) -> Option<()> {
+    let (lhs, op, rhs) = parse_binary_op(ctx)?;
+
+    if !is_primitive_int(ctx, &lhs) || !is_primitive_int(ctx, &rhs) {
+        return None;
+    }
+
+    let start = lhs.syntax().text_range().start();
+    let end = rhs.syntax().text_range().end();
+    let range = TextRange::new(start, end);
+
+    acc.add_group(
+        &GroupLabel("replace_arith".into()),
+        kind.assist_id(),
+        kind.label(),
+        range,
+        |builder| {
+            let method_name = kind.method_name(op);
+
+            builder.replace(range, format!("{lhs}.{method_name}({rhs})"))
+        },
+    )
+}
+
+fn is_primitive_int(ctx: &AssistContext<'_>, expr: &ast::Expr) -> bool {
+    match ctx.sema.type_of_expr(expr) {
+        Some(ty) => ty.adjusted().is_int_or_uint(),
+        _ => false,
+    }
+}
+
+/// Extract the operands of an arithmetic expression (e.g. `1 + 2` or `1.checked_add(2)`)
+fn parse_binary_op(ctx: &AssistContext<'_>) -> Option<(ast::Expr, ArithOp, ast::Expr)> {
+    let expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
+
+    let op = match expr.op_kind() {
+        Some(BinaryOp::ArithOp(ArithOp::Add)) => ArithOp::Add,
+        Some(BinaryOp::ArithOp(ArithOp::Sub)) => ArithOp::Sub,
+        Some(BinaryOp::ArithOp(ArithOp::Mul)) => ArithOp::Mul,
+        Some(BinaryOp::ArithOp(ArithOp::Div)) => ArithOp::Div,
+        _ => return None,
+    };
+
+    let lhs = expr.lhs()?;
+    let rhs = expr.rhs()?;
+
+    Some((lhs, op, rhs))
+}
+
+pub(crate) enum ArithKind {
+    Saturating,
+    Wrapping,
+    Checked,
+}
+
+impl ArithKind {
+    fn assist_id(&self) -> AssistId {
+        let s = match self {
+            ArithKind::Saturating => "replace_arith_with_saturating",
+            ArithKind::Checked => "replace_arith_with_checked",
+            ArithKind::Wrapping => "replace_arith_with_wrapping",
+        };
+
+        AssistId(s, AssistKind::RefactorRewrite)
+    }
+
+    fn label(&self) -> &'static str {
+        match self {
+            ArithKind::Saturating => "Replace arithmetic with call to saturating_*",
+            ArithKind::Checked => "Replace arithmetic with call to checked_*",
+            ArithKind::Wrapping => "Replace arithmetic with call to wrapping_*",
+        }
+    }
+
+    fn method_name(&self, op: ArithOp) -> String {
+        let prefix = match self {
+            ArithKind::Checked => "checked_",
+            ArithKind::Wrapping => "wrapping_",
+            ArithKind::Saturating => "saturating_",
+        };
+
+        let suffix = match op {
+            ArithOp::Add => "add",
+            ArithOp::Sub => "sub",
+            ArithOp::Mul => "mul",
+            ArithOp::Div => "div",
+            _ => unreachable!("this function should only be called with +, -, / or *"),
+        };
+        format!("{prefix}{suffix}")
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::tests::check_assist;
+
+    use super::*;
+
+    #[test]
+    fn arith_kind_method_name() {
+        assert_eq!(ArithKind::Saturating.method_name(ArithOp::Add), "saturating_add");
+        assert_eq!(ArithKind::Checked.method_name(ArithOp::Sub), "checked_sub");
+    }
+
+    #[test]
+    fn replace_arith_with_checked_add() {
+        check_assist(
+            replace_arith_with_checked,
+            r#"
+fn main() {
+    let x = 1 $0+ 2;
+}
+"#,
+            r#"
+fn main() {
+    let x = 1.checked_add(2);
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn replace_arith_with_saturating_add() {
+        check_assist(
+            replace_arith_with_saturating,
+            r#"
+fn main() {
+    let x = 1 $0+ 2;
+}
+"#,
+            r#"
+fn main() {
+    let x = 1.saturating_add(2);
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn replace_arith_with_wrapping_add() {
+        check_assist(
+            replace_arith_with_wrapping,
+            r#"
+fn main() {
+    let x = 1 $0+ 2;
+}
+"#,
+            r#"
+fn main() {
+    let x = 1.wrapping_add(2);
+}
+"#,
+        )
+    }
+}
diff --git a/crates/ide-assists/src/handlers/replace_arith_with_checked.rs b/crates/ide-assists/src/handlers/replace_arith_with_checked.rs
deleted file mode 100644
index ff1fba5818c..00000000000
--- a/crates/ide-assists/src/handlers/replace_arith_with_checked.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use crate::assist_context::{AssistContext, Assists};
-use crate::utils::{replace_arith, ArithKind};
-
-// Assist: replace_arith_with_checked
-//
-// Replaces arithmetic on integers with the `checked_*` equivalent.
-//
-// ```
-// fn main() {
-//   let x = 1 $0+ 2;
-// }
-// ```
-// ->
-// ```
-// fn main() {
-//   let x = 1.checked_add(2);
-// }
-// ```
-pub(crate) fn replace_arith_with_checked(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    replace_arith(acc, ctx, ArithKind::Checked)
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::check_assist;
-
-    use super::*;
-
-    #[test]
-    fn replace_arith_with_saturating_add() {
-        check_assist(
-            replace_arith_with_checked,
-            r#"
-fn main() {
-    let x = 1 $0+ 2;
-}
-"#,
-            r#"
-fn main() {
-    let x = 1.checked_add(2);
-}
-"#,
-        )
-    }
-}
diff --git a/crates/ide-assists/src/handlers/replace_arith_with_saturating.rs b/crates/ide-assists/src/handlers/replace_arith_with_saturating.rs
deleted file mode 100644
index 717875e84f0..00000000000
--- a/crates/ide-assists/src/handlers/replace_arith_with_saturating.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use crate::assist_context::{AssistContext, Assists};
-use crate::utils::{replace_arith, ArithKind};
-
-// Assist: replace_arith_with_saturating
-//
-// Replaces arithmetic on integers with the `saturating_*` equivalent.
-//
-// ```
-// fn main() {
-//   let x = 1 $0+ 2;
-// }
-// ```
-// ->
-// ```
-// fn main() {
-//   let x = 1.saturating_add(2);
-// }
-// ```
-pub(crate) fn replace_arith_with_saturating(
-    acc: &mut Assists,
-    ctx: &AssistContext<'_>,
-) -> Option<()> {
-    replace_arith(acc, ctx, ArithKind::Saturating)
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::check_assist;
-
-    use super::*;
-
-    #[test]
-    fn replace_arith_with_saturating_add() {
-        check_assist(
-            replace_arith_with_saturating,
-            r#"
-fn main() {
-    let x = 1 $0+ 2;
-}
-"#,
-            r#"
-fn main() {
-    let x = 1.saturating_add(2);
-}
-"#,
-        )
-    }
-}
diff --git a/crates/ide-assists/src/handlers/replace_arith_with_wrapping.rs b/crates/ide-assists/src/handlers/replace_arith_with_wrapping.rs
deleted file mode 100644
index e0a90292b19..00000000000
--- a/crates/ide-assists/src/handlers/replace_arith_with_wrapping.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use crate::assist_context::{AssistContext, Assists};
-use crate::utils::{replace_arith, ArithKind};
-
-// Assist: replace_arith_with_wrapping
-//
-// Replaces arithmetic on integers with the `wrapping_*` equivalent.
-//
-// ```
-// fn main() {
-//   let x = 1 $0+ 2;
-// }
-// ```
-// ->
-// ```
-// fn main() {
-//   let x = 1.wrapping_add(2);
-// }
-// ```
-pub(crate) fn replace_arith_with_wrapping(
-    acc: &mut Assists,
-    ctx: &AssistContext<'_>,
-) -> Option<()> {
-    replace_arith(acc, ctx, ArithKind::Wrapping)
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::check_assist;
-
-    use super::*;
-
-    #[test]
-    fn replace_arith_with_saturating_add() {
-        check_assist(
-            replace_arith_with_wrapping,
-            r#"
-fn main() {
-    let x = 1 $0+ 2;
-}
-"#,
-            r#"
-fn main() {
-    let x = 1.wrapping_add(2);
-}
-"#,
-        )
-    }
-}
diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs
index 3938fa09835..0255ffdea3f 100644
--- a/crates/ide-assists/src/lib.rs
+++ b/crates/ide-assists/src/lib.rs
@@ -183,9 +183,7 @@ mod handlers {
     mod replace_derive_with_manual_impl;
     mod replace_if_let_with_match;
     mod replace_or_with_or_else;
-    mod replace_arith_with_checked;
-    mod replace_arith_with_wrapping;
-    mod replace_arith_with_saturating;
+    mod replace_arith_op;
     mod introduce_named_generic;
     mod replace_let_with_if_let;
     mod replace_qualified_name_with_use;
@@ -289,9 +287,9 @@ mod handlers {
             replace_or_with_or_else::replace_or_with_or_else,
             replace_turbofish_with_explicit_type::replace_turbofish_with_explicit_type,
             replace_qualified_name_with_use::replace_qualified_name_with_use,
-            replace_arith_with_wrapping::replace_arith_with_wrapping,
-            replace_arith_with_checked::replace_arith_with_checked,
-            replace_arith_with_saturating::replace_arith_with_saturating,
+            replace_arith_op::replace_arith_with_wrapping,
+            replace_arith_op::replace_arith_with_checked,
+            replace_arith_op::replace_arith_with_saturating,
             sort_items::sort_items,
             split_import::split_import,
             toggle_ignore::toggle_ignore,
diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs
index 0227222c089..db32e7182c4 100644
--- a/crates/ide-assists/src/utils.rs
+++ b/crates/ide-assists/src/utils.rs
@@ -4,27 +4,21 @@ use std::ops;
 
 pub(crate) use gen_trait_fn_body::gen_trait_fn_body;
 use hir::{db::HirDatabase, HirDisplay, Semantics};
-use ide_db::{
-    assists::{AssistId, AssistKind},
-    famous_defs::FamousDefs,
-    path_transform::PathTransform,
-    RootDatabase, SnippetCap,
-};
+use ide_db::{famous_defs::FamousDefs, path_transform::PathTransform, RootDatabase, SnippetCap};
 use stdx::format_to;
 use syntax::{
     ast::{
         self,
         edit::{self, AstNodeEdit},
         edit_in_place::{AttrsOwnerEdit, Removable},
-        make, ArithOp, BinExpr, BinaryOp, Expr, HasArgList, HasAttrs, HasGenericParams, HasName,
-        HasTypeBounds, Whitespace,
+        make, HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace,
     },
-    ted, AstNode, AstToken, Direction, SmolStr, SourceFile,
+    ted, AstNode, AstToken, Direction, SourceFile,
     SyntaxKind::*,
     SyntaxNode, TextRange, TextSize, T,
 };
 
-use crate::assist_context::{AssistContext, Assists, SourceChangeBuilder};
+use crate::assist_context::{AssistContext, SourceChangeBuilder};
 
 pub(crate) mod suggest_name;
 mod gen_trait_fn_body;
@@ -711,113 +705,3 @@ pub(crate) fn convert_param_list_to_arg_list(list: ast::ParamList) -> ast::ArgLi
     }
     make::arg_list(args)
 }
-
-pub(crate) enum ArithKind {
-    Saturating,
-    Wrapping,
-    Checked,
-}
-
-impl ArithKind {
-    fn assist_id(&self) -> AssistId {
-        let s = match self {
-            ArithKind::Saturating => "replace_arith_with_saturating",
-            ArithKind::Checked => "replace_arith_with_checked",
-            ArithKind::Wrapping => "replace_arith_with_wrapping",
-        };
-
-        AssistId(s, AssistKind::RefactorRewrite)
-    }
-
-    fn label(&self) -> &'static str {
-        match self {
-            ArithKind::Saturating => "Replace arithmetic with call to saturating_*",
-            ArithKind::Checked => "Replace arithmetic with call to checked_*",
-            ArithKind::Wrapping => "Replace arithmetic with call to wrapping_*",
-        }
-    }
-
-    fn method_name(&self, op: ArithOp) -> SmolStr {
-        // is this too much effort to avoid an allocation? is there a better way?
-        let mut bytes = [0u8; 14];
-        let prefix = match self {
-            ArithKind::Checked => "checked_",
-            ArithKind::Wrapping => "wrapping_",
-            ArithKind::Saturating => "saturating_",
-        };
-
-        bytes[0..(prefix.len())].copy_from_slice(prefix.as_bytes());
-
-        let suffix = match op {
-            ArithOp::Add => "add",
-            ArithOp::Sub => "sub",
-            ArithOp::Mul => "mul",
-            ArithOp::Div => "div",
-            _ => unreachable!("this function should only be called with +, -, / or *"),
-        };
-
-        bytes[(prefix.len())..(prefix.len() + suffix.len())].copy_from_slice(suffix.as_bytes());
-
-        let len = prefix.len() + suffix.len();
-        let s = core::str::from_utf8(&bytes[0..len]).unwrap();
-        SmolStr::from(s)
-    }
-}
-
-pub(crate) fn replace_arith(
-    acc: &mut Assists,
-    ctx: &AssistContext<'_>,
-    kind: ArithKind,
-) -> Option<()> {
-    let (lhs, op, rhs) = parse_binary_op(ctx)?;
-
-    if !is_primitive_int(ctx, &lhs) || !is_primitive_int(ctx, &rhs) {
-        return None;
-    }
-
-    let start = lhs.syntax().text_range().start();
-    let end = rhs.syntax().text_range().end();
-    let range = TextRange::new(start, end);
-
-    acc.add(kind.assist_id(), kind.label(), range, |builder| {
-        let method_name = kind.method_name(op);
-
-        builder.replace(range, format!("{lhs}.{method_name}({rhs})"))
-    })
-}
-
-fn is_primitive_int(ctx: &AssistContext<'_>, expr: &Expr) -> bool {
-    match ctx.sema.type_of_expr(expr) {
-        Some(ty) => ty.adjusted().is_int_or_uint(),
-        _ => false,
-    }
-}
-
-/// Extract the operands of an arithmetic expression (e.g. `1 + 2` or `1.checked_add(2)`)
-fn parse_binary_op(ctx: &AssistContext<'_>) -> Option<(Expr, ArithOp, Expr)> {
-    let expr = ctx.find_node_at_offset::<BinExpr>()?;
-
-    let op = match expr.op_kind() {
-        Some(BinaryOp::ArithOp(ArithOp::Add)) => ArithOp::Add,
-        Some(BinaryOp::ArithOp(ArithOp::Sub)) => ArithOp::Sub,
-        Some(BinaryOp::ArithOp(ArithOp::Mul)) => ArithOp::Mul,
-        Some(BinaryOp::ArithOp(ArithOp::Div)) => ArithOp::Div,
-        _ => return None,
-    };
-
-    let lhs = expr.lhs()?;
-    let rhs = expr.rhs()?;
-
-    Some((lhs, op, rhs))
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn arith_kind_method_name() {
-        assert_eq!(ArithKind::Saturating.method_name(ArithOp::Add), "saturating_add");
-        assert_eq!(ArithKind::Checked.method_name(ArithOp::Sub), "checked_sub");
-    }
-}