Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21623 from A4-Tacks/replace-is-some-and
feat: offer on is_some_and for replace_is_method_with_if_let_method
Shoyu Vanilla (Flint) 2 months ago
parent e92dad7 · parent 63126cc · commit 8e793d9
-rw-r--r--crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs58
1 files changed, 50 insertions, 8 deletions
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 5a2307739c..d22e951b5d 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,6 +1,6 @@
use either::Either;
use ide_db::syntax_helpers::suggest_name;
-use syntax::ast::{self, AstNode, syntax_factory::SyntaxFactory};
+use syntax::ast::{self, AstNode, HasArgList, syntax_factory::SyntaxFactory};
use crate::{AssistContext, AssistId, Assists, utils::cover_let_chain};
@@ -34,8 +34,9 @@ pub(crate) fn replace_is_method_with_if_let_method(
_ => return None,
};
- let name_ref = call_expr.name_ref()?;
- match name_ref.text().as_str() {
+ let token = call_expr.name_ref()?.ident_token()?;
+ let method_kind = token.text().strip_suffix("_and").unwrap_or(token.text());
+ match method_kind {
"is_some" | "is_ok" => {
let receiver = call_expr.receiver()?;
@@ -47,8 +48,9 @@ pub(crate) fn replace_is_method_with_if_let_method(
} else {
name_generator.for_variable(&receiver, &ctx.sema)
};
+ let (pat, predicate) = method_predicate(&call_expr).unzip();
- let (assist_id, message, text) = if name_ref.text() == "is_some" {
+ let (assist_id, message, text) = if method_kind == "is_some" {
("replace_is_some_with_if_let_some", "Replace `is_some` with `let Some`", "Some")
} else {
("replace_is_ok_with_if_let_ok", "Replace `is_ok` with `let Ok`", "Ok")
@@ -62,19 +64,29 @@ pub(crate) fn replace_is_method_with_if_let_method(
let make = SyntaxFactory::with_mappings();
let mut editor = edit.make_editor(call_expr.syntax());
- let var_pat = make.ident_pat(false, false, make.name(&var_name));
- let pat = make.tuple_struct_pat(make.ident_path(text), [var_pat.into()]);
- let let_expr = make.expr_let(pat.into(), receiver);
+ let var_pat = pat.unwrap_or_else(|| {
+ make.ident_pat(false, false, make.name(&var_name)).into()
+ });
+ let pat = make.tuple_struct_pat(make.ident_path(text), [var_pat]).into();
+ let let_expr = make.expr_let(pat, receiver);
if let Some(cap) = ctx.config.snippet_cap
&& let Some(ast::Pat::TupleStructPat(pat)) = let_expr.pat()
&& let Some(first_var) = pat.fields().next()
+ && predicate.is_none()
{
let placeholder = edit.make_placeholder_snippet(cap);
editor.add_annotation(first_var.syntax(), placeholder);
}
- editor.replace(call_expr.syntax(), let_expr.syntax());
+ let new_expr = if let Some(predicate) = predicate {
+ let op = ast::BinaryOp::LogicOp(ast::LogicOp::And);
+ make.expr_bin(let_expr.into(), op, predicate).into()
+ } else {
+ ast::Expr::from(let_expr)
+ };
+ editor.replace(call_expr.syntax(), new_expr.syntax());
+
editor.add_mappings(make.finish_with_mappings());
edit.add_file_edits(ctx.vfs_file_id(), editor);
},
@@ -84,6 +96,17 @@ pub(crate) fn replace_is_method_with_if_let_method(
}
}
+fn method_predicate(call_expr: &ast::MethodCallExpr) -> Option<(ast::Pat, ast::Expr)> {
+ let argument = call_expr.arg_list()?.args().next()?;
+ match argument {
+ ast::Expr::ClosureExpr(it) => {
+ let pat = it.param_list()?.params().next()?.pat()?;
+ Some((pat, it.body()?))
+ }
+ _ => None,
+ }
+}
+
#[cfg(test)]
mod tests {
use crate::tests::{check_assist, check_assist_not_applicable};
@@ -195,6 +218,25 @@ fn main() {
}
#[test]
+ fn replace_is_some_and_with_if_let_chain_some_works() {
+ check_assist(
+ replace_is_method_with_if_let_method,
+ r#"
+fn main() {
+ let x = Some(1);
+ if x.is_som$0e_and(|it| it != 3) {}
+}
+"#,
+ r#"
+fn main() {
+ let x = Some(1);
+ if let Some(it) = x && it != 3 {}
+}
+"#,
+ );
+ }
+
+ #[test]
fn replace_is_some_with_if_let_some_in_let_chain() {
check_assist(
replace_is_method_with_if_let_method,