mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-12-23 08:48:08 +00:00
Merge pull request #20913 from A4-Tacks/if-let-chain-for-is-method-with-if-let
Fix not applicable on let-chain for replace_is_method_with_if_let_method
This commit is contained in:
commit
803ab10db4
2 changed files with 81 additions and 4 deletions
|
|
@ -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::<ast::IfExpr>()?;
|
||||
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -1133,6 +1133,28 @@ pub(crate) fn tt_from_syntax(node: SyntaxNode) -> Vec<NodeOrToken<ast::TokenTree
|
|||
tt_stack.pop().expect("parent token tree was closed before it was completed").1
|
||||
}
|
||||
|
||||
pub(crate) fn cover_let_chain(mut expr: ast::Expr, range: TextRange) -> Option<ast::Expr> {
|
||||
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| {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue