@@ -6,7 +6,7 @@ use ide_db::{
66 syntax_helpers:: node_ext:: { for_each_tail_expr, walk_expr} ,
77} ;
88use syntax:: {
9- SyntaxKind , T ,
9+ NodeOrToken , SyntaxKind , T ,
1010 ast:: {
1111 self , AstNode ,
1212 Expr :: BinExpr ,
@@ -38,15 +38,27 @@ use crate::{AssistContext, AssistId, Assists, utils::invert_boolean_expression};
3838// }
3939// ```
4040pub ( crate ) fn apply_demorgan ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
41- let mut bin_expr = ctx. find_node_at_offset :: < ast:: BinExpr > ( ) ?;
41+ let mut bin_expr = if let Some ( not) = ctx. find_token_syntax_at_offset ( T ! [ !] )
42+ && let Some ( NodeOrToken :: Node ( next) ) = not. next_sibling_or_token ( )
43+ && let Some ( paren) = ast:: ParenExpr :: cast ( next)
44+ && let Some ( ast:: Expr :: BinExpr ( bin_expr) ) = paren. expr ( )
45+ {
46+ bin_expr
47+ } else {
48+ let bin_expr = ctx. find_node_at_offset :: < ast:: BinExpr > ( ) ?;
49+ let op_range = bin_expr. op_token ( ) ?. text_range ( ) ;
50+
51+ // Is the cursor on the expression's logical operator?
52+ if !op_range. contains_range ( ctx. selection_trimmed ( ) ) {
53+ return None ;
54+ }
55+
56+ bin_expr
57+ } ;
58+
4259 let op = bin_expr. op_kind ( ) ?;
4360 let op_range = bin_expr. op_token ( ) ?. text_range ( ) ;
4461
45- // Is the cursor on the expression's logical operator?
46- if !op_range. contains_range ( ctx. selection_trimmed ( ) ) {
47- return None ;
48- }
49-
5062 // Walk up the tree while we have the same binary operator
5163 while let Some ( parent_expr) = bin_expr. syntax ( ) . parent ( ) . and_then ( ast:: BinExpr :: cast) {
5264 match parent_expr. op_kind ( ) {
@@ -366,6 +378,15 @@ fn f() { !(S <= S || S < S) }
366378 )
367379 }
368380
381+ #[ test]
382+ fn demorgan_on_not ( ) {
383+ check_assist (
384+ apply_demorgan,
385+ "fn f() { $0!(1 || 3 && 4 || 5) }" ,
386+ "fn f() { !1 && !(3 && 4) && !5 }" ,
387+ )
388+ }
389+
369390 #[ test]
370391 fn demorgan_keep_pars_for_op_precedence ( ) {
371392 check_assist (
0 commit comments