@@ -86,16 +86,18 @@ pub fn format_expr(
86
86
rewrite_call ( context, & callee_str, args, inner_span, shape)
87
87
}
88
88
ast:: ExprKind :: Paren ( ref subexpr) => rewrite_paren ( context, subexpr, shape, expr. span ) ,
89
- ast:: ExprKind :: Binary ( ref op, ref lhs, ref rhs) => {
89
+ ast:: ExprKind :: Binary ( op, ref lhs, ref rhs) => {
90
90
// FIXME: format comments between operands and operator
91
- rewrite_pair (
92
- & * * lhs,
93
- & * * rhs,
94
- PairParts :: new ( "" , & format ! ( " {} " , context. snippet( op. span) ) , "" ) ,
95
- context,
96
- shape,
97
- context. config . binop_separator ( ) ,
98
- )
91
+ rewrite_simple_binaries ( context, expr, shape, op) . or_else ( || {
92
+ rewrite_pair (
93
+ & * * lhs,
94
+ & * * rhs,
95
+ PairParts :: new ( "" , & format ! ( " {} " , context. snippet( op. span) ) , "" ) ,
96
+ context,
97
+ shape,
98
+ context. config . binop_separator ( ) ,
99
+ )
100
+ } )
99
101
}
100
102
ast:: ExprKind :: Unary ( ref op, ref subexpr) => rewrite_unary_op ( context, op, subexpr, shape) ,
101
103
ast:: ExprKind :: Struct ( ref path, ref fields, ref base) => rewrite_struct_lit (
@@ -352,6 +354,80 @@ pub fn format_expr(
352
354
} )
353
355
}
354
356
357
+ /// Collect operands that appears in the given binary operator in the opposite order.
358
+ /// e.g. `collect_binary_items(e, ||)` for `a && b || c || d` returns `[d, c, a && b]`.
359
+ fn collect_binary_items < ' a > ( mut expr : & ' a ast:: Expr , binop : ast:: BinOp ) -> Vec < & ' a ast:: Expr > {
360
+ let mut result = vec ! [ ] ;
361
+ let mut prev_lhs = None ;
362
+ loop {
363
+ match expr. node {
364
+ ast:: ExprKind :: Binary ( inner_binop, ref lhs, ref rhs)
365
+ if inner_binop. node == binop. node =>
366
+ {
367
+ result. push ( & * * rhs) ;
368
+ expr = lhs;
369
+ prev_lhs = Some ( lhs) ;
370
+ }
371
+ _ => {
372
+ if let Some ( lhs) = prev_lhs {
373
+ result. push ( lhs) ;
374
+ }
375
+ break ;
376
+ }
377
+ }
378
+ }
379
+ result
380
+ }
381
+
382
+ /// Rewrites a binary expression whose operands fits within a single line.
383
+ fn rewrite_simple_binaries (
384
+ context : & RewriteContext ,
385
+ expr : & ast:: Expr ,
386
+ shape : Shape ,
387
+ op : ast:: BinOp ,
388
+ ) -> Option < String > {
389
+ let op_str = context. snippet ( op. span ) ;
390
+
391
+ // 2 = spaces around a binary operator.
392
+ let sep_overhead = op_str. len ( ) + 2 ;
393
+ let nested_overhead = sep_overhead - 1 ;
394
+
395
+ let nested_shape = ( match context. config . indent_style ( ) {
396
+ IndentStyle :: Visual => shape. visual_indent ( 0 ) ,
397
+ IndentStyle :: Block => shape. block_indent ( context. config . tab_spaces ( ) ) ,
398
+ } ) . with_max_width ( context. config ) ;
399
+ let nested_shape = match context. config . binop_separator ( ) {
400
+ SeparatorPlace :: Back => nested_shape. sub_width ( nested_overhead) ?,
401
+ SeparatorPlace :: Front => nested_shape. offset_left ( nested_overhead) ?,
402
+ } ;
403
+
404
+ let opt_rewrites: Option < Vec < _ > > = collect_binary_items ( expr, op)
405
+ . iter ( )
406
+ . rev ( )
407
+ . map ( |e| e. rewrite ( context, nested_shape) )
408
+ . collect ( ) ;
409
+ if let Some ( rewrites) = opt_rewrites {
410
+ if rewrites. iter ( ) . all ( |e| :: utils:: is_single_line ( e) ) {
411
+ let total_width = rewrites. iter ( ) . map ( |s| s. len ( ) ) . sum :: < usize > ( )
412
+ + sep_overhead * ( rewrites. len ( ) - 1 ) ;
413
+
414
+ let sep_str = if total_width <= shape. width {
415
+ format ! ( " {} " , op_str)
416
+ } else {
417
+ let indent_str = nested_shape. indent . to_string_with_newline ( context. config ) ;
418
+ match context. config . binop_separator ( ) {
419
+ SeparatorPlace :: Back => format ! ( " {}{}" , op_str. trim_right( ) , indent_str) ,
420
+ SeparatorPlace :: Front => format ! ( "{}{} " , indent_str, op_str. trim_left( ) ) ,
421
+ }
422
+ } ;
423
+
424
+ return wrap_str ( rewrites. join ( & sep_str) , context. config . max_width ( ) , shape) ;
425
+ }
426
+ }
427
+
428
+ None
429
+ }
430
+
355
431
#[ derive( new, Clone , Copy ) ]
356
432
pub struct PairParts < ' a > {
357
433
prefix : & ' a str ,
0 commit comments