]> git.lizzy.rs Git - rust.git/commitdiff
Change `single_let()` and `is_pattern_cond()` to free functions
authorChayim Refael Friedman <chayimfr@gmail.com>
Mon, 21 Feb 2022 06:15:21 +0000 (08:15 +0200)
committerChayim Refael Friedman <chayimfr@gmail.com>
Mon, 21 Feb 2022 06:34:36 +0000 (08:34 +0200)
crates/ide_assists/src/handlers/convert_bool_then.rs
crates/ide_assists/src/handlers/convert_to_guarded_return.rs
crates/ide_assists/src/handlers/convert_while_to_loop.rs
crates/ide_assists/src/handlers/invert_if.rs
crates/ide_assists/src/handlers/replace_if_let_with_match.rs
crates/ide_db/src/helpers/node_ext.rs
crates/syntax/src/ast/node_ext.rs

index 0bf2abe493492c5254e3778bb6e31dccfbc2c0e0..274718e6ea90e900466640d40db4d8cdc2415af7 100644 (file)
@@ -2,7 +2,7 @@
 use ide_db::{
     helpers::{
         for_each_tail_expr,
-        node_ext::{block_as_lone_tail, preorder_expr},
+        node_ext::{block_as_lone_tail, is_pattern_cond, preorder_expr},
         FamousDefs,
     },
     RootDatabase,
@@ -45,7 +45,7 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext) ->
         return None;
     }
 
-    let cond = expr.condition().filter(|cond| !cond.is_pattern_cond())?;
+    let cond = expr.condition().filter(|cond| !is_pattern_cond(cond.clone()))?;
     let then = expr.then_branch()?;
     let else_ = match expr.else_branch()? {
         ast::ElseBranch::Block(b) => b,
index 9a80db6a83f73a1edbdaab861c8821a9f3fc0ede..193d1cdfb2439cc4ce3a31491a27a328b562cb34 100644 (file)
@@ -1,5 +1,6 @@
 use std::iter::once;
 
+use ide_db::helpers::node_ext::{is_pattern_cond, single_let};
 use syntax::{
     ast::{
         self,
@@ -48,8 +49,8 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
     let cond = if_expr.condition()?;
 
     // Check if there is an IfLet that we can handle.
-    let (if_let_pat, cond_expr) = if cond.is_pattern_cond() {
-        let let_ = cond.single_let()?;
+    let (if_let_pat, cond_expr) = if is_pattern_cond(cond.clone()) {
+        let let_ = single_let(cond)?;
         match let_.pat() {
             Some(ast::Pat::TupleStructPat(pat)) if pat.fields().count() == 1 => {
                 let path = pat.path()?;
index 30b4daec9d923f03f8e40d97b8f3396d56591447..0fa2dcfbde1f7bea4a6f898631697e47b548316a 100644 (file)
@@ -1,5 +1,6 @@
 use std::iter::once;
 
+use ide_db::helpers::node_ext::is_pattern_cond;
 use syntax::{
     ast::{
         self,
@@ -54,7 +55,7 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext) -> O
             let break_block =
                 make::block_expr(once(make::expr_stmt(make::expr_break(None)).into()), None)
                     .indent(while_indent_level);
-            let block_expr = if while_cond.is_pattern_cond() {
+            let block_expr = if is_pattern_cond(while_cond.clone()) {
                 let if_expr = make::expr_if(while_cond, while_body, Some(break_block.into()));
                 let stmts = once(make::expr_stmt(if_expr).into());
                 make::block_expr(stmts, None)
index 8f99c4db67bb03f62269d50ce00b02dc32f671a3..46f11f4af3248b849cba98974e9a35ce0519a644 100644 (file)
@@ -1,3 +1,4 @@
+use ide_db::helpers::node_ext::is_pattern_cond;
 use syntax::{
     ast::{self, AstNode},
     T,
@@ -36,7 +37,7 @@ pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
 
     let cond = expr.condition()?;
     // This assist should not apply for if-let.
-    if cond.is_pattern_cond() {
+    if is_pattern_cond(cond.clone()) {
         return None;
     }
 
index 2f35f74c5af17b10883b0b16ebfd92da42a57278..b594c64c412dac5eb2a794768645257e6414887f 100644 (file)
@@ -1,7 +1,12 @@
 use std::iter::{self, successors};
 
 use either::Either;
-use ide_db::{defs::NameClass, ty_filter::TryEnum, RootDatabase};
+use ide_db::{
+    defs::NameClass,
+    helpers::node_ext::{is_pattern_cond, single_let},
+    ty_filter::TryEnum,
+    RootDatabase,
+};
 use syntax::{
     ast::{
         self,
@@ -61,7 +66,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
         }
     });
     let scrutinee_to_be_expr = if_expr.condition()?;
-    let scrutinee_to_be_expr = match scrutinee_to_be_expr.single_let() {
+    let scrutinee_to_be_expr = match single_let(scrutinee_to_be_expr.clone()) {
         Some(cond) => cond.expr()?,
         None => scrutinee_to_be_expr,
     };
@@ -70,7 +75,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
     let mut cond_bodies = Vec::new();
     for if_expr in if_exprs {
         let cond = if_expr.condition()?;
-        let cond = match cond.single_let() {
+        let cond = match single_let(cond.clone()) {
             Some(let_) => {
                 let pat = let_.pat()?;
                 let expr = let_.expr()?;
@@ -84,7 +89,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
                 Either::Left(pat)
             }
             // Multiple `let`, unsupported.
-            None if cond.is_pattern_cond() => return None,
+            None if is_pattern_cond(cond.clone()) => return None,
             None => Either::Right(cond),
         };
         let body = if_expr.then_branch()?;
index 82178ed74962259190017accaa9cb872948b8a7b..5df3ed1366f15d5d5d1787e1a4bd663fa45f1773 100644 (file)
@@ -216,3 +216,29 @@ pub fn vis_eq(this: &ast::Visibility, other: &ast::Visibility) -> bool {
         _ => false,
     }
 }
+
+/// Returns the `let` only if there is exactly one (that is, `let pat = expr`
+/// or `((let pat = expr))`, but not `let pat = expr && expr` or `non_let_expr`).
+pub fn single_let(expr: ast::Expr) -> Option<ast::LetExpr> {
+    match expr {
+        ast::Expr::ParenExpr(expr) => expr.expr().and_then(single_let),
+        ast::Expr::LetExpr(expr) => Some(expr),
+        _ => None,
+    }
+}
+
+pub fn is_pattern_cond(expr: ast::Expr) -> bool {
+    match expr {
+        ast::Expr::BinExpr(expr)
+            if expr.op_kind() == Some(ast::BinaryOp::LogicOp(ast::LogicOp::And)) =>
+        {
+            expr.lhs()
+                .map(is_pattern_cond)
+                .or_else(|| expr.rhs().map(is_pattern_cond))
+                .unwrap_or(false)
+        }
+        ast::Expr::ParenExpr(expr) => expr.expr().map_or(false, is_pattern_cond),
+        ast::Expr::LetExpr(_) => true,
+        _ => false,
+    }
+}
index 2915e7aab1a984a8023f30700a1aef842185489a..5ff6519c9ccf93c1c218458da9b960ae1b723282 100644 (file)
@@ -528,42 +528,6 @@ pub fn generic_param_list(&self) -> Option<ast::GenericParamList> {
     }
 }
 
-impl ast::Expr {
-    /// Returns the `let` only if there is exactly one (that is, `let pat = expr`
-    /// or `((let pat = expr))`, but not `let pat = expr && expr` or `non_let_expr`).
-    pub fn single_let(&self) -> Option<ast::LetExpr> {
-        return get_pat(self.clone());
-
-        fn get_pat(expr: ast::Expr) -> Option<ast::LetExpr> {
-            match expr {
-                ast::Expr::ParenExpr(expr) => expr.expr().and_then(get_pat),
-                ast::Expr::LetExpr(expr) => Some(expr),
-                _ => None,
-            }
-        }
-    }
-
-    pub fn is_pattern_cond(&self) -> bool {
-        return contains_let(self.clone());
-
-        fn contains_let(expr: ast::Expr) -> bool {
-            match expr {
-                ast::Expr::BinExpr(expr)
-                    if expr.op_kind() == Some(ast::BinaryOp::LogicOp(ast::LogicOp::And)) =>
-                {
-                    expr.lhs()
-                        .map(contains_let)
-                        .or_else(|| expr.rhs().map(contains_let))
-                        .unwrap_or(false)
-                }
-                ast::Expr::ParenExpr(expr) => expr.expr().map_or(false, contains_let),
-                ast::Expr::LetExpr(_) => true,
-                _ => false,
-            }
-        }
-    }
-}
-
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub enum FieldKind {
     Name(ast::NameRef),