@@ -153,7 +153,13 @@ enum CommentPosition {
153
153
Top ,
154
154
}
155
155
156
- // An expression plus trailing `?`s to be formatted together.
156
+ /// Information about an expression in a chain.
157
+ struct SubExpr {
158
+ expr : ast:: Expr ,
159
+ is_method_call_receiver : bool ,
160
+ }
161
+
162
+ /// An expression plus trailing `?`s to be formatted together.
157
163
#[ derive( Debug ) ]
158
164
struct ChainItem {
159
165
kind : ChainItemKind ,
@@ -166,7 +172,10 @@ struct ChainItem {
166
172
// would remove a lot of cloning.
167
173
#[ derive( Debug ) ]
168
174
enum ChainItemKind {
169
- Parent ( ast:: Expr ) ,
175
+ Parent {
176
+ expr : ast:: Expr ,
177
+ parens : bool ,
178
+ } ,
170
179
MethodCall (
171
180
ast:: PathSegment ,
172
181
Vec < ast:: GenericArg > ,
@@ -181,7 +190,7 @@ enum ChainItemKind {
181
190
impl ChainItemKind {
182
191
fn is_block_like ( & self , context : & RewriteContext < ' _ > , reps : & str ) -> bool {
183
192
match self {
184
- ChainItemKind :: Parent ( ref expr) => utils:: is_block_expr ( context, expr, reps) ,
193
+ ChainItemKind :: Parent { expr, .. } => utils:: is_block_expr ( context, expr, reps) ,
185
194
ChainItemKind :: MethodCall ( ..)
186
195
| ChainItemKind :: StructField ( ..)
187
196
| ChainItemKind :: TupleField ( ..)
@@ -199,7 +208,11 @@ impl ChainItemKind {
199
208
}
200
209
}
201
210
202
- fn from_ast ( context : & RewriteContext < ' _ > , expr : & ast:: Expr ) -> ( ChainItemKind , Span ) {
211
+ fn from_ast (
212
+ context : & RewriteContext < ' _ > ,
213
+ expr : & ast:: Expr ,
214
+ is_method_call_receiver : bool ,
215
+ ) -> ( ChainItemKind , Span ) {
203
216
let ( kind, span) = match expr. kind {
204
217
ast:: ExprKind :: MethodCall ( ref call) => {
205
218
let types = if let Some ( ref generic_args) = call. seg . args {
@@ -236,7 +249,19 @@ impl ChainItemKind {
236
249
let span = mk_sp ( nested. span . hi ( ) , expr. span . hi ( ) ) ;
237
250
( ChainItemKind :: Await , span)
238
251
}
239
- _ => return ( ChainItemKind :: Parent ( expr. clone ( ) ) , expr. span ) ,
252
+ _ => {
253
+ return (
254
+ ChainItemKind :: Parent {
255
+ expr : expr. clone ( ) ,
256
+ parens : is_method_call_receiver
257
+ && matches ! (
258
+ & expr. kind,
259
+ ast:: ExprKind :: Lit ( lit) if crate :: expr:: lit_ends_in_dot( lit)
260
+ ) ,
261
+ } ,
262
+ expr. span ,
263
+ ) ;
264
+ }
240
265
} ;
241
266
242
267
// Remove comments from the span.
@@ -249,7 +274,14 @@ impl Rewrite for ChainItem {
249
274
fn rewrite ( & self , context : & RewriteContext < ' _ > , shape : Shape ) -> Option < String > {
250
275
let shape = shape. sub_width ( self . tries ) ?;
251
276
let rewrite = match self . kind {
252
- ChainItemKind :: Parent ( ref expr) => expr. rewrite ( context, shape) ?,
277
+ ChainItemKind :: Parent {
278
+ ref expr,
279
+ parens : true ,
280
+ } => crate :: expr:: rewrite_paren ( context, & expr, shape, expr. span ) ?,
281
+ ChainItemKind :: Parent {
282
+ ref expr,
283
+ parens : false ,
284
+ } => expr. rewrite ( context, shape) ?,
253
285
ChainItemKind :: MethodCall ( ref segment, ref types, ref exprs) => {
254
286
Self :: rewrite_method_call ( segment. ident , types, exprs, self . span , context, shape) ?
255
287
}
@@ -273,8 +305,9 @@ impl Rewrite for ChainItem {
273
305
}
274
306
275
307
impl ChainItem {
276
- fn new ( context : & RewriteContext < ' _ > , expr : & ast:: Expr , tries : usize ) -> ChainItem {
277
- let ( kind, span) = ChainItemKind :: from_ast ( context, expr) ;
308
+ fn new ( context : & RewriteContext < ' _ > , expr : & SubExpr , tries : usize ) -> ChainItem {
309
+ let ( kind, span) =
310
+ ChainItemKind :: from_ast ( context, & expr. expr , expr. is_method_call_receiver ) ;
278
311
ChainItem { kind, tries, span }
279
312
}
280
313
@@ -327,7 +360,7 @@ impl Chain {
327
360
let mut rev_children = vec ! [ ] ;
328
361
let mut sub_tries = 0 ;
329
362
for subexpr in & subexpr_list {
330
- match subexpr. kind {
363
+ match subexpr. expr . kind {
331
364
ast:: ExprKind :: Try ( _) => sub_tries += 1 ,
332
365
_ => {
333
366
rev_children. push ( ChainItem :: new ( context, subexpr, sub_tries) ) ;
@@ -442,24 +475,33 @@ impl Chain {
442
475
443
476
// Returns a Vec of the prefixes of the chain.
444
477
// E.g., for input `a.b.c` we return [`a.b.c`, `a.b`, 'a']
445
- fn make_subexpr_list ( expr : & ast:: Expr , context : & RewriteContext < ' _ > ) -> Vec < ast:: Expr > {
446
- let mut subexpr_list = vec ! [ expr. clone( ) ] ;
478
+ fn make_subexpr_list ( expr : & ast:: Expr , context : & RewriteContext < ' _ > ) -> Vec < SubExpr > {
479
+ let mut subexpr_list = vec ! [ SubExpr {
480
+ expr: expr. clone( ) ,
481
+ is_method_call_receiver: false ,
482
+ } ] ;
447
483
448
484
while let Some ( subexpr) = Self :: pop_expr_chain ( subexpr_list. last ( ) . unwrap ( ) , context) {
449
- subexpr_list. push ( subexpr. clone ( ) ) ;
485
+ subexpr_list. push ( subexpr) ;
450
486
}
451
487
452
488
subexpr_list
453
489
}
454
490
455
491
// Returns the expression's subexpression, if it exists. When the subexpr
456
492
// is a try! macro, we'll convert it to shorthand when the option is set.
457
- fn pop_expr_chain ( expr : & ast:: Expr , context : & RewriteContext < ' _ > ) -> Option < ast:: Expr > {
458
- match expr. kind {
459
- ast:: ExprKind :: MethodCall ( ref call) => Some ( Self :: convert_try ( & call. receiver , context) ) ,
493
+ fn pop_expr_chain ( expr : & SubExpr , context : & RewriteContext < ' _ > ) -> Option < SubExpr > {
494
+ match expr. expr . kind {
495
+ ast:: ExprKind :: MethodCall ( ref call) => Some ( SubExpr {
496
+ expr : Self :: convert_try ( & call. receiver , context) ,
497
+ is_method_call_receiver : true ,
498
+ } ) ,
460
499
ast:: ExprKind :: Field ( ref subexpr, _)
461
500
| ast:: ExprKind :: Try ( ref subexpr)
462
- | ast:: ExprKind :: Await ( ref subexpr, _) => Some ( Self :: convert_try ( subexpr, context) ) ,
501
+ | ast:: ExprKind :: Await ( ref subexpr, _) => Some ( SubExpr {
502
+ expr : Self :: convert_try ( subexpr, context) ,
503
+ is_method_call_receiver : false ,
504
+ } ) ,
463
505
_ => None ,
464
506
}
465
507
}
0 commit comments