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