@@ -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