Skip to content

Commit 6afb6c6

Browse files
fix demorgan assist to handle method call
1 parent 5ffe3f4 commit 6afb6c6

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

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

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,19 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
132132
.filter(|prefix_expr| matches!(prefix_expr.op_kind(), Some(ast::UnaryOp::Not)))
133133
.map(ast::Expr::PrefixExpr);
134134

135+
// Check if the parenthesized expression is the receiver of a method call
136+
let is_method_receiver = paren_expr
137+
.as_ref()
138+
.and_then(|paren_expr| paren_expr.syntax().parent())
139+
.and_then(ast::MethodCallExpr::cast)
140+
.is_some_and(|method_call| {
141+
paren_expr.as_ref().is_some_and(|paren_expr| {
142+
method_call
143+
.receiver()
144+
.is_some_and(|receiver| receiver.syntax() == paren_expr.syntax())
145+
})
146+
});
147+
135148
let mut editor;
136149
if let Some(paren_expr) = paren_expr {
137150
if let Some(neg_expr) = neg_expr {
@@ -151,7 +164,18 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
151164
cov_mark::hit!(demorgan_double_parens);
152165
editor = builder.make_editor(paren_expr.syntax());
153166

154-
editor.replace(paren_expr.syntax(), add_bang_paren(&make, demorganed).syntax());
167+
// If this is a method receiver, we need to keep parentheses around the negated expression
168+
if is_method_receiver {
169+
editor.replace(
170+
paren_expr.syntax(),
171+
make.expr_paren(add_bang_paren(&make, demorganed)).syntax(),
172+
);
173+
} else {
174+
editor.replace(
175+
paren_expr.syntax(),
176+
add_bang_paren(&make, demorganed).syntax(),
177+
);
178+
}
155179
}
156180
} else {
157181
editor = builder.make_editor(bin_expr.syntax());
@@ -636,4 +660,31 @@ fn main() {
636660
"#,
637661
);
638662
}
663+
664+
#[test]
665+
fn demorgan_method_call_receiver() {
666+
check_assist(
667+
apply_demorgan,
668+
"fn f() { (x ||$0 !y).then_some(42) }",
669+
"fn f() { (!(!x && y)).then_some(42) }",
670+
);
671+
}
672+
673+
#[test]
674+
fn demorgan_method_call_receiver_complex() {
675+
check_assist(
676+
apply_demorgan,
677+
"fn f() { (a && b ||$0 c && d).then_some(42) }",
678+
"fn f() { (!(!(a && b) && !(c && d))).then_some(42) }",
679+
);
680+
}
681+
682+
#[test]
683+
fn demorgan_method_call_receiver_chained() {
684+
check_assist(
685+
apply_demorgan,
686+
"fn f() { (a ||$0 b).then_some(42).or(Some(0)) }",
687+
"fn f() { (!(!a && !b)).then_some(42).or(Some(0)) }",
688+
);
689+
}
639690
}

0 commit comments

Comments
 (0)