@@ -15,7 +15,7 @@ use syntax::print::pprust;
15
15
use syntax:: symbol:: { kw, sym} ;
16
16
use syntax:: symbol:: Symbol ;
17
17
use syntax:: util:: parser;
18
- use syntax_pos:: Span ;
18
+ use syntax_pos:: { Span , BytePos } ;
19
19
20
20
use rustc:: hir;
21
21
@@ -353,31 +353,41 @@ declare_lint! {
353
353
declare_lint_pass ! ( UnusedParens => [ UNUSED_PARENS ] ) ;
354
354
355
355
impl UnusedParens {
356
+
357
+ fn is_expr_parens_necessary ( inner : & ast:: Expr , followed_by_block : bool ) -> bool {
358
+ followed_by_block && match inner. node {
359
+ ast:: ExprKind :: Ret ( _) | ast:: ExprKind :: Break ( ..) => true ,
360
+ _ => parser:: contains_exterior_struct_lit ( & inner) ,
361
+ }
362
+ }
363
+
356
364
fn check_unused_parens_expr ( & self ,
357
- cx : & EarlyContext < ' _ > ,
358
- value : & ast:: Expr ,
359
- msg : & str ,
360
- followed_by_block : bool ) {
365
+ cx : & EarlyContext < ' _ > ,
366
+ value : & ast:: Expr ,
367
+ msg : & str ,
368
+ followed_by_block : bool ,
369
+ left_pos : Option < BytePos > ,
370
+ right_pos : Option < BytePos > ) {
361
371
match value. node {
362
372
ast:: ExprKind :: Paren ( ref inner) => {
363
- let necessary = followed_by_block && match inner. node {
364
- ast:: ExprKind :: Ret ( _) | ast:: ExprKind :: Break ( ..) => true ,
365
- _ => parser:: contains_exterior_struct_lit ( & inner) ,
366
- } ;
367
- if !necessary {
373
+ if !Self :: is_expr_parens_necessary ( inner, followed_by_block) {
368
374
let expr_text = if let Ok ( snippet) = cx. sess ( ) . source_map ( )
369
375
. span_to_snippet ( value. span ) {
370
376
snippet
371
377
} else {
372
378
pprust:: expr_to_string ( value)
373
379
} ;
374
- Self :: remove_outer_parens ( cx, value. span , & expr_text, msg) ;
380
+ let keep_space = (
381
+ left_pos. map ( |s| s >= value. span . lo ( ) ) . unwrap_or ( false ) ,
382
+ right_pos. map ( |s| s <= value. span . hi ( ) ) . unwrap_or ( false ) ,
383
+ ) ;
384
+ Self :: remove_outer_parens ( cx, value. span , & expr_text, msg, keep_space) ;
375
385
}
376
386
}
377
387
ast:: ExprKind :: Let ( _, ref expr) => {
378
388
// FIXME(#60336): Properly handle `let true = (false && true)`
379
389
// actually needing the parenthesis.
380
- self . check_unused_parens_expr ( cx, expr, "`let` head expression" , followed_by_block) ;
390
+ self . check_unused_parens_expr ( cx, expr, "`let` head expression" , followed_by_block, None , None ) ;
381
391
}
382
392
_ => { }
383
393
}
@@ -394,11 +404,11 @@ impl UnusedParens {
394
404
} else {
395
405
pprust:: pat_to_string ( value)
396
406
} ;
397
- Self :: remove_outer_parens ( cx, value. span , & pattern_text, msg) ;
407
+ Self :: remove_outer_parens ( cx, value. span , & pattern_text, msg, ( false , false ) ) ;
398
408
}
399
409
}
400
410
401
- fn remove_outer_parens ( cx : & EarlyContext < ' _ > , span : Span , pattern : & str , msg : & str ) {
411
+ fn remove_outer_parens ( cx : & EarlyContext < ' _ > , span : Span , pattern : & str , msg : & str , keep_space : ( bool , bool ) ) {
402
412
let span_msg = format ! ( "unnecessary parentheses around {}" , msg) ;
403
413
let mut err = cx. struct_span_lint ( UNUSED_PARENS , span, & span_msg) ;
404
414
let mut ate_left_paren = false ;
@@ -427,9 +437,17 @@ impl UnusedParens {
427
437
} ) ;
428
438
429
439
let replace = {
430
- let mut replace = String :: from ( " " ) ;
431
- replace. push_str ( parens_removed) ;
432
- replace. push ( ' ' ) ;
440
+ let mut replace = if keep_space. 0 {
441
+ let mut s = String :: from ( " " ) ;
442
+ s. push_str ( parens_removed) ;
443
+ s
444
+ } else {
445
+ String :: from ( parens_removed)
446
+ } ;
447
+
448
+ if keep_space. 1 {
449
+ replace. push ( ' ' ) ;
450
+ }
433
451
replace
434
452
} ;
435
453
@@ -446,14 +464,35 @@ impl UnusedParens {
446
464
impl EarlyLintPass for UnusedParens {
447
465
fn check_expr ( & mut self , cx : & EarlyContext < ' _ > , e : & ast:: Expr ) {
448
466
use syntax:: ast:: ExprKind :: * ;
449
- let ( value, msg, followed_by_block) = match e. node {
450
- If ( ref cond, ..) => ( cond, "`if` condition" , true ) ,
451
- While ( ref cond, ..) => ( cond, "`while` condition" , true ) ,
452
- ForLoop ( _, ref cond, ..) => ( cond, "`for` head expression" , true ) ,
453
- Match ( ref head, _) => ( head, "`match` head expression" , true ) ,
454
- Ret ( Some ( ref value) ) => ( value, "`return` value" , false ) ,
455
- Assign ( _, ref value) => ( value, "assigned value" , false ) ,
456
- AssignOp ( .., ref value) => ( value, "assigned value" , false ) ,
467
+ let ( value, msg, followed_by_block, left_pos, right_pos) = match e. node {
468
+ If ( ref cond, ref block, ..) => {
469
+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 2 ) ;
470
+ let right = block. span . lo ( ) ;
471
+ ( cond, "`if` condition" , true , Some ( left) , Some ( right) )
472
+ }
473
+
474
+ While ( ref cond, ref block, ..) => {
475
+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 5 ) ;
476
+ let right = block. span . lo ( ) ;
477
+ ( cond, "`while` condition" , true , Some ( left) , Some ( right) )
478
+ } ,
479
+
480
+ ForLoop ( _, ref cond, ref block, ..) => {
481
+ ( cond, "`for` head expression" , true , None , Some ( block. span . lo ( ) ) )
482
+ }
483
+
484
+ Match ( ref head, _) => {
485
+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 5 ) ;
486
+ ( head, "`match` head expression" , true , Some ( left) , None )
487
+ }
488
+
489
+ Ret ( Some ( ref value) ) => {
490
+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 3 ) ;
491
+ ( value, "`return` value" , false , Some ( left) , None )
492
+ }
493
+
494
+ Assign ( _, ref value) => ( value, "assigned value" , false , None , None ) ,
495
+ AssignOp ( .., ref value) => ( value, "assigned value" , false , None , None ) ,
457
496
// either function/method call, or something this lint doesn't care about
458
497
ref call_or_other => {
459
498
let ( args_to_check, call_kind) = match * call_or_other {
@@ -475,12 +514,12 @@ impl EarlyLintPass for UnusedParens {
475
514
}
476
515
let msg = format ! ( "{} argument" , call_kind) ;
477
516
for arg in args_to_check {
478
- self . check_unused_parens_expr ( cx, arg, & msg, false ) ;
517
+ self . check_unused_parens_expr ( cx, arg, & msg, false , None , None ) ;
479
518
}
480
519
return ;
481
520
}
482
521
} ;
483
- self . check_unused_parens_expr ( cx, & value, msg, followed_by_block) ;
522
+ self . check_unused_parens_expr ( cx, & value, msg, followed_by_block, left_pos , right_pos ) ;
484
523
}
485
524
486
525
fn check_pat ( & mut self , cx : & EarlyContext < ' _ > , p : & ast:: Pat ) {
@@ -500,7 +539,7 @@ impl EarlyLintPass for UnusedParens {
500
539
fn check_stmt ( & mut self , cx : & EarlyContext < ' _ > , s : & ast:: Stmt ) {
501
540
if let ast:: StmtKind :: Local ( ref local) = s. node {
502
541
if let Some ( ref value) = local. init {
503
- self . check_unused_parens_expr ( cx, & value, "assigned value" , false ) ;
542
+ self . check_unused_parens_expr ( cx, & value, "assigned value" , false , None , None ) ;
504
543
}
505
544
}
506
545
}
0 commit comments