@@ -34,19 +34,11 @@ pub(crate) fn rewrite_all_pairs(
34
34
shape : Shape ,
35
35
context : & RewriteContext < ' _ > ,
36
36
) -> Option < String > {
37
- // First we try formatting on one line.
38
- if let Some ( list) = expr. flatten ( false ) {
39
- if let Some ( r) = rewrite_pairs_one_line ( & list, shape, context) {
40
- return Some ( r) ;
41
- }
42
- }
43
-
44
- // We can't format on line, so try many. When we flatten here we make sure
45
- // to only flatten pairs with the same operator, that way we don't
46
- // necessarily need one line per sub-expression, but we don't do anything
47
- // too funny wrt precedence.
48
- expr. flatten ( true )
49
- . and_then ( |list| rewrite_pairs_multiline ( & list, shape, context) )
37
+ expr. flatten ( context, shape) . and_then ( |list| {
38
+ // First we try formatting on one line.
39
+ rewrite_pairs_one_line ( & list, shape, context)
40
+ . or_else ( || rewrite_pairs_multiline ( & list, shape, context) )
41
+ } )
50
42
}
51
43
52
44
// This may return a multi-line result since we allow the last expression to go
@@ -61,22 +53,23 @@ fn rewrite_pairs_one_line<T: Rewrite>(
61
53
let mut result = String :: new ( ) ;
62
54
let base_shape = shape. block ( ) ;
63
55
64
- for ( e, s) in list. list . iter ( ) . zip ( list. separators . iter ( ) ) {
65
- let cur_shape = base_shape. offset_left ( last_line_width ( & result) ) ?;
66
- let rewrite = e. rewrite ( context, cur_shape) ?;
56
+ for ( ( _, rewrite) , s) in list. list . iter ( ) . zip ( list. separators . iter ( ) ) {
57
+ if let Some ( rewrite) = rewrite {
58
+ if !is_single_line ( & rewrite) || result. len ( ) > shape. width {
59
+ return None ;
60
+ }
67
61
68
- if !is_single_line ( & rewrite) || result. len ( ) > shape. width {
62
+ result. push_str ( & rewrite) ;
63
+ result. push ( ' ' ) ;
64
+ result. push_str ( s) ;
65
+ result. push ( ' ' ) ;
66
+ } else {
69
67
return None ;
70
68
}
71
-
72
- result. push_str ( & rewrite) ;
73
- result. push ( ' ' ) ;
74
- result. push_str ( s) ;
75
- result. push ( ' ' ) ;
76
69
}
77
70
78
71
let prefix_len = result. len ( ) ;
79
- let last = list. list . last ( ) . unwrap ( ) ;
72
+ let last = list. list . last ( ) ? . 0 ;
80
73
let cur_shape = base_shape. offset_left ( last_line_width ( & result) ) ?;
81
74
let last_rewrite = last. rewrite ( context, cur_shape) ?;
82
75
result. push_str ( & last_rewrite) ;
@@ -112,10 +105,9 @@ fn rewrite_pairs_multiline<T: Rewrite>(
112
105
let indent_str = nested_shape. indent . to_string_with_newline ( context. config ) ;
113
106
let mut result = String :: new ( ) ;
114
107
115
- let rewrite = list. list [ 0 ] . rewrite ( context, shape) ?;
116
- result. push_str ( & rewrite) ;
108
+ result. push_str ( & list. list [ 0 ] . 1 . as_ref ( ) ?) ;
117
109
118
- for ( e , s) in list. list [ 1 ..] . iter ( ) . zip ( list. separators . iter ( ) ) {
110
+ for ( ( e , default_rw ) , s) in list. list [ 1 ..] . iter ( ) . zip ( list. separators . iter ( ) ) {
119
111
// The following test checks if we should keep two subexprs on the same
120
112
// line. We do this if not doing so would create an orphan and there is
121
113
// enough space to do so.
@@ -139,24 +131,20 @@ fn rewrite_pairs_multiline<T: Rewrite>(
139
131
}
140
132
}
141
133
142
- let nested_overhead = s. len ( ) + 1 ;
143
- let line_shape = match context. config . binop_separator ( ) {
134
+ match context. config . binop_separator ( ) {
144
135
SeparatorPlace :: Back => {
145
136
result. push ( ' ' ) ;
146
137
result. push_str ( s) ;
147
138
result. push_str ( & indent_str) ;
148
- nested_shape. sub_width ( nested_overhead) ?
149
139
}
150
140
SeparatorPlace :: Front => {
151
141
result. push_str ( & indent_str) ;
152
142
result. push_str ( s) ;
153
143
result. push ( ' ' ) ;
154
- nested_shape. offset_left ( nested_overhead) ?
155
144
}
156
- } ;
145
+ }
157
146
158
- let rewrite = e. rewrite ( context, line_shape) ?;
159
- result. push_str ( & rewrite) ;
147
+ result. push_str ( & default_rw. as_ref ( ) ?) ;
160
148
}
161
149
Some ( result)
162
150
}
@@ -250,27 +238,46 @@ where
250
238
251
239
// A pair which forms a tree and can be flattened (e.g., binops).
252
240
trait FlattenPair : Rewrite + Sized {
253
- // If `_same_op` is `true`, then we only combine binops with the same
254
- // operator into the list. E.g,, if the source is `a * b + c`, if `_same_op`
255
- // is true, we make `[(a * b), c]` if `_same_op` is false, we make
256
- // `[a, b, c]`
257
- fn flatten ( & self , _same_op : bool ) -> Option < PairList < ' _ , ' _ , Self > > {
241
+ fn flatten ( & self , _: & RewriteContext < ' _ > , _: Shape ) -> Option < PairList < ' _ , ' _ , Self > > {
258
242
None
259
243
}
260
244
}
261
245
262
246
struct PairList < ' a , ' b , T : Rewrite > {
263
- list : Vec < & ' b T > ,
247
+ list : Vec < ( & ' b T , Option < String > ) > ,
264
248
separators : Vec < & ' a str > ,
265
249
}
266
250
267
251
impl FlattenPair for ast:: Expr {
268
- fn flatten ( & self , same_op : bool ) -> Option < PairList < ' _ , ' _ , ast:: Expr > > {
252
+ fn flatten (
253
+ & self ,
254
+ context : & RewriteContext < ' _ > ,
255
+ shape : Shape ,
256
+ ) -> Option < PairList < ' _ , ' _ , ast:: Expr > > {
269
257
let top_op = match self . node {
270
258
ast:: ExprKind :: Binary ( op, _, _) => op. node ,
271
259
_ => return None ,
272
260
} ;
273
261
262
+ let default_rewrite = |node : & ast:: Expr , sep : usize , is_first : bool | {
263
+ if is_first {
264
+ return node. rewrite ( context, shape) ;
265
+ }
266
+ let nested_overhead = sep + 1 ;
267
+ let rhs_offset = shape. rhs_overhead ( & context. config ) ;
268
+ let nested_shape = ( match context. config . indent_style ( ) {
269
+ IndentStyle :: Visual => shape. visual_indent ( 0 ) ,
270
+ IndentStyle :: Block => shape. block_indent ( context. config . tab_spaces ( ) ) ,
271
+ } )
272
+ . with_max_width ( & context. config )
273
+ . sub_width ( rhs_offset) ?;
274
+ let default_shape = match context. config . binop_separator ( ) {
275
+ SeparatorPlace :: Back => nested_shape. sub_width ( nested_overhead) ?,
276
+ SeparatorPlace :: Front => nested_shape. offset_left ( nested_overhead) ?,
277
+ } ;
278
+ node. rewrite ( context, default_shape)
279
+ } ;
280
+
274
281
// Turn a tree of binop expressions into a list using a depth-first,
275
282
// in-order traversal.
276
283
let mut stack = vec ! [ ] ;
@@ -279,12 +286,14 @@ impl FlattenPair for ast::Expr {
279
286
let mut node = self ;
280
287
loop {
281
288
match node. node {
282
- ast:: ExprKind :: Binary ( op, ref lhs, _) if !same_op || op. node == top_op => {
289
+ ast:: ExprKind :: Binary ( op, ref lhs, _) if op. node == top_op => {
283
290
stack. push ( node) ;
284
291
node = lhs;
285
292
}
286
293
_ => {
287
- list. push ( node) ;
294
+ let op_len = separators. last ( ) . map_or ( 0 , |s : & & str | s. len ( ) ) ;
295
+ let rw = default_rewrite ( node, op_len, list. is_empty ( ) ) ;
296
+ list. push ( ( node, rw) ) ;
288
297
if let Some ( pop) = stack. pop ( ) {
289
298
match pop. node {
290
299
ast:: ExprKind :: Binary ( op, _, ref rhs) => {
0 commit comments