@@ -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,46 @@ 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 (
391
+ cx, expr,
392
+ "`let` head expression" ,
393
+ followed_by_block,
394
+ None , None
395
+ ) ;
381
396
}
382
397
_ => { }
383
398
}
@@ -394,11 +409,15 @@ impl UnusedParens {
394
409
} else {
395
410
pprust:: pat_to_string ( value)
396
411
} ;
397
- Self :: remove_outer_parens ( cx, value. span , & pattern_text, msg) ;
412
+ Self :: remove_outer_parens ( cx, value. span , & pattern_text, msg, ( false , false ) ) ;
398
413
}
399
414
}
400
415
401
- fn remove_outer_parens ( cx : & EarlyContext < ' _ > , span : Span , pattern : & str , msg : & str ) {
416
+ fn remove_outer_parens ( cx : & EarlyContext < ' _ > ,
417
+ span : Span ,
418
+ pattern : & str ,
419
+ msg : & str ,
420
+ keep_space : ( bool , bool ) ) {
402
421
let span_msg = format ! ( "unnecessary parentheses around {}" , msg) ;
403
422
let mut err = cx. struct_span_lint ( UNUSED_PARENS , span, & span_msg) ;
404
423
let mut ate_left_paren = false ;
@@ -424,11 +443,27 @@ impl UnusedParens {
424
443
} ,
425
444
_ => false ,
426
445
}
427
- } ) . to_owned ( ) ;
446
+ } ) ;
447
+
448
+ let replace = {
449
+ let mut replace = if keep_space. 0 {
450
+ let mut s = String :: from ( " " ) ;
451
+ s. push_str ( parens_removed) ;
452
+ s
453
+ } else {
454
+ String :: from ( parens_removed)
455
+ } ;
456
+
457
+ if keep_space. 1 {
458
+ replace. push ( ' ' ) ;
459
+ }
460
+ replace
461
+ } ;
462
+
428
463
err. span_suggestion_short (
429
464
span,
430
465
"remove these parentheses" ,
431
- parens_removed ,
466
+ replace ,
432
467
Applicability :: MachineApplicable ,
433
468
) ;
434
469
err. emit ( ) ;
@@ -438,14 +473,35 @@ impl UnusedParens {
438
473
impl EarlyLintPass for UnusedParens {
439
474
fn check_expr ( & mut self , cx : & EarlyContext < ' _ > , e : & ast:: Expr ) {
440
475
use syntax:: ast:: ExprKind :: * ;
441
- let ( value, msg, followed_by_block) = match e. node {
442
- If ( ref cond, ..) => ( cond, "`if` condition" , true ) ,
443
- While ( ref cond, ..) => ( cond, "`while` condition" , true ) ,
444
- ForLoop ( _, ref cond, ..) => ( cond, "`for` head expression" , true ) ,
445
- Match ( ref head, _) => ( head, "`match` head expression" , true ) ,
446
- Ret ( Some ( ref value) ) => ( value, "`return` value" , false ) ,
447
- Assign ( _, ref value) => ( value, "assigned value" , false ) ,
448
- AssignOp ( .., ref value) => ( value, "assigned value" , false ) ,
476
+ let ( value, msg, followed_by_block, left_pos, right_pos) = match e. node {
477
+ If ( ref cond, ref block, ..) => {
478
+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 2 ) ;
479
+ let right = block. span . lo ( ) ;
480
+ ( cond, "`if` condition" , true , Some ( left) , Some ( right) )
481
+ }
482
+
483
+ While ( ref cond, ref block, ..) => {
484
+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 5 ) ;
485
+ let right = block. span . lo ( ) ;
486
+ ( cond, "`while` condition" , true , Some ( left) , Some ( right) )
487
+ } ,
488
+
489
+ ForLoop ( _, ref cond, ref block, ..) => {
490
+ ( cond, "`for` head expression" , true , None , Some ( block. span . lo ( ) ) )
491
+ }
492
+
493
+ Match ( ref head, _) => {
494
+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 5 ) ;
495
+ ( head, "`match` head expression" , true , Some ( left) , None )
496
+ }
497
+
498
+ Ret ( Some ( ref value) ) => {
499
+ let left = e. span . lo ( ) + syntax_pos:: BytePos ( 3 ) ;
500
+ ( value, "`return` value" , false , Some ( left) , None )
501
+ }
502
+
503
+ Assign ( _, ref value) => ( value, "assigned value" , false , None , None ) ,
504
+ AssignOp ( .., ref value) => ( value, "assigned value" , false , None , None ) ,
449
505
// either function/method call, or something this lint doesn't care about
450
506
ref call_or_other => {
451
507
let ( args_to_check, call_kind) = match * call_or_other {
@@ -467,12 +523,12 @@ impl EarlyLintPass for UnusedParens {
467
523
}
468
524
let msg = format ! ( "{} argument" , call_kind) ;
469
525
for arg in args_to_check {
470
- self . check_unused_parens_expr ( cx, arg, & msg, false ) ;
526
+ self . check_unused_parens_expr ( cx, arg, & msg, false , None , None ) ;
471
527
}
472
528
return ;
473
529
}
474
530
} ;
475
- self . check_unused_parens_expr ( cx, & value, msg, followed_by_block) ;
531
+ self . check_unused_parens_expr ( cx, & value, msg, followed_by_block, left_pos , right_pos ) ;
476
532
}
477
533
478
534
fn check_pat ( & mut self , cx : & EarlyContext < ' _ > , p : & ast:: Pat ) {
@@ -492,7 +548,7 @@ impl EarlyLintPass for UnusedParens {
492
548
fn check_stmt ( & mut self , cx : & EarlyContext < ' _ > , s : & ast:: Stmt ) {
493
549
if let ast:: StmtKind :: Local ( ref local) = s. node {
494
550
if let Some ( ref value) = local. init {
495
- self . check_unused_parens_expr ( cx, & value, "assigned value" , false ) ;
551
+ self . check_unused_parens_expr ( cx, & value, "assigned value" , false , None , None ) ;
496
552
}
497
553
}
498
554
}
0 commit comments