Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/apply_demorgan.rs')
-rw-r--r--crates/ide-assists/src/handlers/apply_demorgan.rs89
1 files changed, 84 insertions, 5 deletions
diff --git a/crates/ide-assists/src/handlers/apply_demorgan.rs b/crates/ide-assists/src/handlers/apply_demorgan.rs
index b87a757047..10262445a2 100644
--- a/crates/ide-assists/src/handlers/apply_demorgan.rs
+++ b/crates/ide-assists/src/handlers/apply_demorgan.rs
@@ -37,7 +37,7 @@ use crate::{AssistContext, AssistId, Assists, utils::invert_boolean_expression};
// if !(x == 4 && y >= 3.14) {}
// }
// ```
-pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_, '_>) -> Option<()> {
let mut bin_expr = if let Some(not) = ctx.find_token_syntax_at_offset(T![!])
&& let Some(NodeOrToken::Node(next)) = not.next_sibling_or_token()
&& let Some(paren) = ast::ParenExpr::cast(next)
@@ -189,8 +189,17 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
// }
// }
// ```
-pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
- let method_call: ast::MethodCallExpr = ctx.find_node_at_offset()?;
+pub(crate) fn apply_demorgan_iterator(
+ acc: &mut Assists,
+ ctx: &AssistContext<'_, '_>,
+) -> Option<()> {
+ let method_call: ast::MethodCallExpr = ctx.find_node_at_offset().or_else(|| {
+ let parent = ctx.find_token_syntax_at_offset(T![!])?.parent()?;
+ match ast::PrefixExpr::cast(parent)?.expr()? {
+ ast::Expr::MethodCallExpr(method_call) => Some(method_call),
+ _ => None,
+ }
+ })?;
let (name, arg_expr) = validate_method_call_expr(ctx, &method_call)?;
let ast::Expr::ClosureExpr(closure_expr) = arg_expr else { return None };
@@ -210,6 +219,8 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>
let new_name = match name.text().as_str() {
"all" => make.name_ref("any"),
"any" => make.name_ref("all"),
+ "is_some_and" => make.name_ref("is_none_or"),
+ "is_none_or" => make.name_ref("is_some_and"),
_ => unreachable!(),
};
editor.replace(name.syntax(), new_name.syntax());
@@ -245,14 +256,17 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>
/// Ensures that the method call is to `Iterator::all` or `Iterator::any`.
fn validate_method_call_expr(
- ctx: &AssistContext<'_>,
+ ctx: &AssistContext<'_, '_>,
method_call: &ast::MethodCallExpr,
) -> Option<(ast::NameRef, ast::Expr)> {
let name_ref = method_call.name_ref()?;
+ let arg_expr = method_call.arg_list()?.args().next()?;
+ if name_ref.text() == "is_some_and" || name_ref.text() == "is_none_or" {
+ return Some((name_ref, arg_expr));
+ }
if name_ref.text() != "all" && name_ref.text() != "any" {
return None;
}
- let arg_expr = method_call.arg_list()?.args().next()?;
let sema = &ctx.sema;
@@ -394,6 +408,26 @@ fn f() { if let 1 = 1 &&$0 true { } }
}
#[test]
+ fn demorgan_iterator_on_not() {
+ check_assist(
+ apply_demorgan_iterator,
+ r#"
+//- minicore: iterator
+fn main() {
+ let arr = [1, 2, 3];
+ let cond = $0!arr.into_iter().all(|num| num != 4);
+}
+"#,
+ r#"
+fn main() {
+ let arr = [1, 2, 3];
+ let cond = arr.into_iter().any(|num| num == 4);
+}
+"#,
+ );
+ }
+
+ #[test]
fn demorgan_keep_pars_for_op_precedence() {
check_assist(
apply_demorgan,
@@ -644,6 +678,51 @@ fn main() {
}
#[test]
+ fn demorgan_option_is_some_and() {
+ check_assist(
+ apply_demorgan_iterator,
+ r#"
+//- minicore: option
+fn main() {
+ let cond = Some(2);
+ if !cond.$0is_some_and(|num| num > 3) {
+ println!("foo");
+ }
+}
+"#,
+ r#"
+fn main() {
+ let cond = Some(2);
+ if cond.is_none_or(|num| num <= 3) {
+ println!("foo");
+ }
+}
+"#,
+ );
+
+ check_assist(
+ apply_demorgan_iterator,
+ r#"
+//- minicore: option
+fn main() {
+ let cond = Some(2);
+ if !cond.$0is_none_or(|num| num > 3) {
+ println!("foo");
+ }
+}
+"#,
+ r#"
+fn main() {
+ let cond = Some(2);
+ if cond.is_some_and(|num| num <= 3) {
+ println!("foo");
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
fn demorgan_method_call_receiver() {
check_assist(
apply_demorgan,