diff --git a/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs index f507cae1bb0d..c57fd4d439dc 100644 --- a/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs +++ b/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs @@ -1,7 +1,7 @@ use ide_db::syntax_helpers::suggest_name; use syntax::ast::{self, AstNode, syntax_factory::SyntaxFactory}; -use crate::{AssistContext, AssistId, Assists}; +use crate::{AssistContext, AssistId, Assists, utils::cover_let_chain}; // Assist: replace_is_some_with_if_let_some // @@ -27,13 +27,11 @@ pub(crate) fn replace_is_method_with_if_let_method( let if_expr = ctx.find_node_at_offset::()?; let cond = if_expr.condition()?; + let cond = cover_let_chain(cond, ctx.selection_trimmed())?; let call_expr = match cond { ast::Expr::MethodCallExpr(call) => call, _ => return None, }; - if ctx.offset() > if_expr.then_branch()?.stmt_list()?.l_curly_token()?.text_range().end() { - return None; - } let name_ref = call_expr.name_ref()?; match name_ref.text().as_str() { @@ -195,6 +193,63 @@ fn main() { ); } + #[test] + fn replace_is_some_with_if_let_some_in_let_chain() { + check_assist( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Some(1); + let cond = true; + if cond && x.is_som$0e() {} +} +"#, + r#" +fn main() { + let x = Some(1); + let cond = true; + if cond && let Some(${0:x1}) = x {} +} +"#, + ); + + check_assist( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Some(1); + let cond = true; + if x.is_som$0e() && cond {} +} +"#, + r#" +fn main() { + let x = Some(1); + let cond = true; + if let Some(${0:x1}) = x && cond {} +} +"#, + ); + + check_assist( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Some(1); + let cond = true; + if cond && x.is_som$0e() && cond {} +} +"#, + r#" +fn main() { + let x = Some(1); + let cond = true; + if cond && let Some(${0:x1}) = x && cond {} +} +"#, + ); + } + #[test] fn replace_is_some_with_if_let_some_not_applicable_after_l_curly() { check_assist_not_applicable( diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs index 5a3c5a39dac7..e43516f6b963 100644 --- a/crates/ide-assists/src/utils.rs +++ b/crates/ide-assists/src/utils.rs @@ -1133,6 +1133,28 @@ pub(crate) fn tt_from_syntax(node: SyntaxNode) -> Vec Option { + if !expr.syntax().text_range().contains_range(range) { + return None; + } + loop { + let (chain_expr, rest) = if let ast::Expr::BinExpr(bin_expr) = &expr + && bin_expr.op_kind() == Some(ast::BinaryOp::LogicOp(ast::LogicOp::And)) + { + (bin_expr.rhs(), bin_expr.lhs()) + } else { + (Some(expr), None) + }; + + if let Some(chain_expr) = chain_expr + && chain_expr.syntax().text_range().contains_range(range) + { + break Some(chain_expr); + } + expr = rest?; + } +} + pub fn is_body_const(sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr) -> bool { let mut is_const = true; preorder_expr(expr, &mut |ev| {