Skip to content

Commit 4bf516e

Browse files
authored
Merge pull request #20973 from Natural-selection1/demorgan
fix demorgan assist to handle method call
2 parents 3668c75 + 06668b6 commit 4bf516e

File tree

1 file changed

+52
-28
lines changed

1 file changed

+52
-28
lines changed

crates/ide-assists/src/handlers/apply_demorgan.rs

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -124,40 +124,37 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
124124
op_range,
125125
|builder| {
126126
let make = SyntaxFactory::with_mappings();
127-
let paren_expr = bin_expr.syntax().parent().and_then(ast::ParenExpr::cast);
128-
let neg_expr = paren_expr
129-
.clone()
127+
let (target_node, result_expr) = if let Some(neg_expr) = bin_expr
128+
.syntax()
129+
.parent()
130+
.and_then(ast::ParenExpr::cast)
130131
.and_then(|paren_expr| paren_expr.syntax().parent())
131132
.and_then(ast::PrefixExpr::cast)
132133
.filter(|prefix_expr| matches!(prefix_expr.op_kind(), Some(ast::UnaryOp::Not)))
133-
.map(ast::Expr::PrefixExpr);
134-
135-
let mut editor;
136-
if let Some(paren_expr) = paren_expr {
137-
if let Some(neg_expr) = neg_expr {
138-
cov_mark::hit!(demorgan_double_negation);
139-
let parent = neg_expr.syntax().parent();
140-
editor = builder.make_editor(neg_expr.syntax());
141-
142-
if parent.is_some_and(|parent| {
143-
demorganed.needs_parens_in_place_of(&parent, neg_expr.syntax())
144-
}) {
145-
cov_mark::hit!(demorgan_keep_parens_for_op_precedence2);
146-
editor.replace(neg_expr.syntax(), make.expr_paren(demorganed).syntax());
147-
} else {
148-
editor.replace(neg_expr.syntax(), demorganed.syntax());
149-
};
150-
} else {
151-
cov_mark::hit!(demorgan_double_parens);
152-
editor = builder.make_editor(paren_expr.syntax());
134+
{
135+
cov_mark::hit!(demorgan_double_negation);
136+
(ast::Expr::from(neg_expr).syntax().clone(), demorganed)
137+
} else if let Some(paren_expr) =
138+
bin_expr.syntax().parent().and_then(ast::ParenExpr::cast)
139+
{
140+
cov_mark::hit!(demorgan_double_parens);
141+
(paren_expr.syntax().clone(), add_bang_paren(&make, demorganed))
142+
} else {
143+
(bin_expr.syntax().clone(), add_bang_paren(&make, demorganed))
144+
};
153145

154-
editor.replace(paren_expr.syntax(), add_bang_paren(&make, demorganed).syntax());
155-
}
146+
let final_expr = if target_node
147+
.parent()
148+
.is_some_and(|p| result_expr.needs_parens_in_place_of(&p, &target_node))
149+
{
150+
cov_mark::hit!(demorgan_keep_parens_for_op_precedence2);
151+
make.expr_paren(result_expr).into()
156152
} else {
157-
editor = builder.make_editor(bin_expr.syntax());
158-
editor.replace(bin_expr.syntax(), add_bang_paren(&make, demorganed).syntax());
159-
}
153+
result_expr
154+
};
160155

156+
let mut editor = builder.make_editor(&target_node);
157+
editor.replace(&target_node, final_expr.syntax());
161158
editor.add_mappings(make.finish_with_mappings());
162159
builder.add_file_edits(ctx.vfs_file_id(), editor);
163160
},
@@ -636,4 +633,31 @@ fn main() {
636633
"#,
637634
);
638635
}
636+
637+
#[test]
638+
fn demorgan_method_call_receiver() {
639+
check_assist(
640+
apply_demorgan,
641+
"fn f() { (x ||$0 !y).then_some(42) }",
642+
"fn f() { (!(!x && y)).then_some(42) }",
643+
);
644+
}
645+
646+
#[test]
647+
fn demorgan_method_call_receiver_complex() {
648+
check_assist(
649+
apply_demorgan,
650+
"fn f() { (a && b ||$0 c && d).then_some(42) }",
651+
"fn f() { (!(!(a && b) && !(c && d))).then_some(42) }",
652+
);
653+
}
654+
655+
#[test]
656+
fn demorgan_method_call_receiver_chained() {
657+
check_assist(
658+
apply_demorgan,
659+
"fn f() { (a ||$0 b).then_some(42).or(Some(0)) }",
660+
"fn f() { (!(!a && !b)).then_some(42).or(Some(0)) }",
661+
);
662+
}
639663
}

0 commit comments

Comments
 (0)