@@ -6,9 +6,16 @@ use ide_db::{
6
6
syntax_helpers:: node_ext:: { for_each_tail_expr, walk_expr} ,
7
7
} ;
8
8
use syntax:: {
9
- ast:: { self , syntax_factory:: SyntaxFactory , AstNode , Expr :: BinExpr , HasArgList } ,
9
+ ast:: {
10
+ self ,
11
+ prec:: { precedence, ExprPrecedence } ,
12
+ syntax_factory:: SyntaxFactory ,
13
+ AstNode ,
14
+ Expr :: BinExpr ,
15
+ HasArgList ,
16
+ } ,
10
17
syntax_editor:: { Position , SyntaxEditor } ,
11
- SyntaxKind , SyntaxNode , T ,
18
+ SyntaxKind , T ,
12
19
} ;
13
20
14
21
use crate :: { utils:: invert_boolean_expression, AssistContext , AssistId , AssistKind , Assists } ;
@@ -52,9 +59,9 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
52
59
}
53
60
54
61
let op = bin_expr. op_kind ( ) ?;
55
- let inv_token = match op {
56
- ast:: BinaryOp :: LogicOp ( ast:: LogicOp :: And ) => SyntaxKind :: PIPE2 ,
57
- ast:: BinaryOp :: LogicOp ( ast:: LogicOp :: Or ) => SyntaxKind :: AMP2 ,
62
+ let ( inv_token, prec ) = match op {
63
+ ast:: BinaryOp :: LogicOp ( ast:: LogicOp :: And ) => ( SyntaxKind :: PIPE2 , ExprPrecedence :: LOr ) ,
64
+ ast:: BinaryOp :: LogicOp ( ast:: LogicOp :: Or ) => ( SyntaxKind :: AMP2 , ExprPrecedence :: LAnd ) ,
58
65
_ => return None ,
59
66
} ;
60
67
@@ -65,33 +72,33 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
65
72
editor. replace ( demorganed. op_token ( ) ?, make. token ( inv_token) ) ;
66
73
67
74
let mut exprs = VecDeque :: from ( [
68
- ( bin_expr. lhs ( ) ?, demorganed. lhs ( ) ?) ,
69
- ( bin_expr. rhs ( ) ?, demorganed. rhs ( ) ?) ,
75
+ ( bin_expr. lhs ( ) ?, demorganed. lhs ( ) ?, prec ) ,
76
+ ( bin_expr. rhs ( ) ?, demorganed. rhs ( ) ?, prec ) ,
70
77
] ) ;
71
78
72
- while let Some ( ( expr, dm ) ) = exprs. pop_front ( ) {
79
+ while let Some ( ( expr, demorganed , prec ) ) = exprs. pop_front ( ) {
73
80
if let BinExpr ( bin_expr) = & expr {
74
- if let BinExpr ( cbin_expr) = & dm {
81
+ if let BinExpr ( cbin_expr) = & demorganed {
75
82
if op == bin_expr. op_kind ( ) ? {
76
83
editor. replace ( cbin_expr. op_token ( ) ?, make. token ( inv_token) ) ;
77
- exprs. push_back ( ( bin_expr. lhs ( ) ?, cbin_expr. lhs ( ) ?) ) ;
78
- exprs. push_back ( ( bin_expr. rhs ( ) ?, cbin_expr. rhs ( ) ?) ) ;
84
+ exprs. push_back ( ( bin_expr. lhs ( ) ?, cbin_expr. lhs ( ) ?, prec ) ) ;
85
+ exprs. push_back ( ( bin_expr. rhs ( ) ?, cbin_expr. rhs ( ) ?, prec ) ) ;
79
86
} else {
80
87
let mut inv = invert_boolean_expression ( & make, expr) ;
81
- if needs_parens_in_place_of ( & inv, & dm . syntax ( ) . parent ( ) ? , & dm ) {
88
+ if precedence ( & inv) . needs_parentheses_in ( prec ) {
82
89
inv = make. expr_paren ( inv) . into ( ) ;
83
90
}
84
- editor. replace ( dm . syntax ( ) , inv. syntax ( ) ) ;
91
+ editor. replace ( demorganed . syntax ( ) , inv. syntax ( ) ) ;
85
92
}
86
93
} else {
87
94
return None ;
88
95
}
89
96
} else {
90
- let mut inv = invert_boolean_expression ( & make, dm . clone ( ) ) ;
91
- if needs_parens_in_place_of ( & inv, & dm . syntax ( ) . parent ( ) ? , & dm ) {
97
+ let mut inv = invert_boolean_expression ( & make, demorganed . clone ( ) ) ;
98
+ if precedence ( & inv) . needs_parentheses_in ( prec ) {
92
99
inv = make. expr_paren ( inv) . into ( ) ;
93
100
}
94
- editor. replace ( dm . syntax ( ) , inv. syntax ( ) ) ;
101
+ editor. replace ( demorganed . syntax ( ) , inv. syntax ( ) ) ;
95
102
}
96
103
}
97
104
@@ -121,7 +128,7 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
121
128
let parent = neg_expr. syntax ( ) . parent ( ) ;
122
129
editor = builder. make_editor ( neg_expr. syntax ( ) ) ;
123
130
124
- if parent. is_some_and ( |parent| demorganed. needs_parens_in ( parent) ) {
131
+ if parent. is_some_and ( |parent| demorganed. needs_parens_in ( & parent) ) {
125
132
cov_mark:: hit!( demorgan_keep_parens_for_op_precedence2) ;
126
133
editor. replace ( neg_expr. syntax ( ) , make. expr_paren ( demorganed) . syntax ( ) ) ;
127
134
} else {
@@ -271,30 +278,6 @@ fn add_bang_paren(make: &SyntaxFactory, expr: ast::Expr) -> ast::Expr {
271
278
make. expr_prefix ( T ! [ !] , make. expr_paren ( expr) . into ( ) ) . into ( )
272
279
}
273
280
274
- fn needs_parens_in_place_of (
275
- this : & ast:: Expr ,
276
- parent : & SyntaxNode ,
277
- in_place_of : & ast:: Expr ,
278
- ) -> bool {
279
- assert_eq ! ( Some ( parent) , in_place_of. syntax( ) . parent( ) . as_ref( ) ) ;
280
-
281
- let child_idx = parent
282
- . children ( )
283
- . enumerate ( )
284
- . find_map ( |( i, it) | if & it == in_place_of. syntax ( ) { Some ( i) } else { None } )
285
- . unwrap ( ) ;
286
- let parent = parent. clone_subtree ( ) ;
287
- let subtree_place = parent. children ( ) . nth ( child_idx) . unwrap ( ) ;
288
-
289
- let mut editor = SyntaxEditor :: new ( parent) ;
290
- editor. replace ( subtree_place, this. syntax ( ) ) ;
291
- let edit = editor. finish ( ) ;
292
-
293
- let replaced = edit. new_root ( ) . children ( ) . nth ( child_idx) . unwrap ( ) ;
294
- let replaced = ast:: Expr :: cast ( replaced) . unwrap ( ) ;
295
- replaced. needs_parens_in ( edit. new_root ( ) . clone ( ) )
296
- }
297
-
298
281
#[ cfg( test) ]
299
282
mod tests {
300
283
use super :: * ;
0 commit comments