@@ -13,10 +13,14 @@ use codemap::SpanUtils;
13
13
use rewrite:: { Rewrite , RewriteContext } ;
14
14
use utils:: { wrap_str, format_mutability} ;
15
15
use lists:: { format_item_list, itemize_list} ;
16
- use expr:: { rewrite_unary_prefix, rewrite_pair, rewrite_tuple } ;
16
+ use expr:: { rewrite_unary_prefix, rewrite_pair} ;
17
17
use types:: rewrite_path;
18
+ use super :: Spanned ;
19
+ use comment:: FindUncommented ;
18
20
19
- use syntax:: ast:: { BindingMode , Pat , PatKind , FieldPat } ;
21
+ use syntax:: ast:: { self , BindingMode , Pat , PatKind , FieldPat } ;
22
+ use syntax:: ptr;
23
+ use syntax:: codemap:: { self , BytePos , Span } ;
20
24
21
25
impl Rewrite for Pat {
22
26
fn rewrite ( & self , context : & RewriteContext , width : usize , offset : Indent ) -> Option < String > {
@@ -60,49 +64,19 @@ impl Rewrite for Pat {
60
64
let prefix = format ! ( "&{}" , format_mutability( mutability) ) ;
61
65
rewrite_unary_prefix ( context, & prefix, & * * pat, width, offset)
62
66
}
63
- // FIXME(#1021): Handle `..` in tuple / tuple struct patterns (RFC 1492)
64
67
PatKind :: Tuple ( ref items, dotdot_pos) => {
65
- if dotdot_pos. is_some ( ) {
66
- return None ;
67
- }
68
- rewrite_tuple ( context,
69
- items. iter ( ) . map ( |x| & * * x) ,
70
- self . span ,
71
- width,
72
- offset)
68
+ rewrite_tuple_pat ( items, dotdot_pos, None , self . span , context, width, offset)
73
69
}
74
70
PatKind :: Path ( ref path) => rewrite_path ( context, true , None , path, width, offset) ,
75
71
PatKind :: TupleStruct ( ref path, ref pat_vec, dotdot_pos) => {
76
72
let path_str = try_opt ! ( rewrite_path( context, true , None , path, width, offset) ) ;
77
-
78
- // FIXME(#1021): Handle `..` in tuple / tuple struct patterns (RFC 1492)
79
- match dotdot_pos {
80
- Some ( _) => Some ( format ! ( "{}(..)" , path_str) ) ,
81
- None => {
82
- if pat_vec. is_empty ( ) {
83
- Some ( path_str)
84
- } else {
85
- // 2 = "()".len()
86
- let width = try_opt ! ( width. checked_sub( path_str. len( ) + 2 ) ) ;
87
- // 1 = "(".len()
88
- let offset = offset + path_str. len ( ) + 1 ;
89
- let items = itemize_list ( context. codemap ,
90
- pat_vec. iter ( ) ,
91
- ")" ,
92
- |item| item. span . lo ,
93
- |item| item. span . hi ,
94
- |item| item. rewrite ( context, width, offset) ,
95
- context. codemap . span_after ( self . span , "(" ) ,
96
- self . span . hi ) ;
97
- Some ( format ! ( "{}({})" ,
98
- path_str,
99
- try_opt!( format_item_list( items,
100
- width,
101
- offset,
102
- context. config) ) ) )
103
- }
104
- }
105
- }
73
+ rewrite_tuple_pat ( pat_vec,
74
+ dotdot_pos,
75
+ Some ( path_str) ,
76
+ self . span ,
77
+ context,
78
+ width,
79
+ offset)
106
80
}
107
81
PatKind :: Lit ( ref expr) => expr. rewrite ( context, width, offset) ,
108
82
PatKind :: Vec ( ref prefix, ref slice_pat, ref suffix) => {
@@ -190,3 +164,87 @@ impl Rewrite for FieldPat {
190
164
}
191
165
}
192
166
}
167
+
168
+ enum TaplePatField < ' a > {
169
+ Pat ( & ' a ptr:: P < ast:: Pat > ) ,
170
+ Dotdot ( BytePos , BytePos ) ,
171
+ }
172
+
173
+ impl < ' a > Rewrite for TaplePatField < ' a > {
174
+ fn rewrite ( & self , context : & RewriteContext , width : usize , offset : Indent ) -> Option < String > {
175
+ match * self {
176
+ TaplePatField :: Pat ( ref p) => p. rewrite ( context, width, offset) ,
177
+ TaplePatField :: Dotdot ( ..) => Some ( ".." . to_string ( ) ) ,
178
+ }
179
+ }
180
+ }
181
+
182
+ impl < ' a > Spanned for TaplePatField < ' a > {
183
+ fn span ( & self ) -> Span {
184
+ match * self {
185
+ TaplePatField :: Pat ( ref p) => p. span ( ) ,
186
+ TaplePatField :: Dotdot ( lo, hi) => {
187
+ Span {
188
+ lo : lo,
189
+ hi : hi,
190
+ expn_id : codemap:: NO_EXPANSION ,
191
+ }
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+ fn rewrite_tuple_pat ( pats : & [ ptr:: P < ast:: Pat > ] ,
198
+ dotdot_pos : Option < usize > ,
199
+ path_str : Option < String > ,
200
+ span : Span ,
201
+ context : & RewriteContext ,
202
+ width : usize ,
203
+ offset : Indent )
204
+ -> Option < String > {
205
+ let mut pat_vec: Vec < _ > = pats. into_iter ( ) . map ( |x| TaplePatField :: Pat ( x) ) . collect ( ) ;
206
+
207
+ if let Some ( pos) = dotdot_pos {
208
+ let snippet = context. snippet ( span) ;
209
+ let lo = span. lo + BytePos ( snippet. find_uncommented ( ".." ) . unwrap ( ) as u32 ) ;
210
+ // 2 == "..".len()
211
+ let dotdot = TaplePatField :: Dotdot ( lo, lo + BytePos ( 2 ) ) ;
212
+
213
+ if pat_vec. is_empty ( ) {
214
+ pat_vec = vec ! [ dotdot] ;
215
+ } else {
216
+ pat_vec. insert ( pos, dotdot) ;
217
+ }
218
+ }
219
+
220
+ if pat_vec. is_empty ( ) {
221
+ path_str
222
+ } else {
223
+ // add comma if `(x,)`
224
+ let add_comma = path_str. is_none ( ) && pat_vec. len ( ) == 1 && dotdot_pos. is_none ( ) ;
225
+
226
+ let path_len = path_str. as_ref ( ) . map ( |p| p. len ( ) ) . unwrap_or ( 0 ) ;
227
+ // 2 = "()".len()
228
+ let width = try_opt ! ( width. checked_sub( path_len + 2 ) ) ;
229
+ // 1 = "(".len()
230
+ let offset = offset + path_len + 1 ;
231
+ let items = itemize_list ( context. codemap ,
232
+ pat_vec. iter ( ) ,
233
+ if add_comma { ",)" } else { ")" } ,
234
+ |item| item. span ( ) . lo ,
235
+ |item| item. span ( ) . hi ,
236
+ |item| item. rewrite ( context, width, offset) ,
237
+ context. codemap . span_after ( span, "(" ) ,
238
+ span. hi - BytePos ( 1 ) ) ;
239
+
240
+ let list = try_opt ! ( format_item_list( items, width, offset, context. config) ) ;
241
+
242
+ match path_str {
243
+ Some ( path_str) => Some ( format ! ( "{}({})" , path_str, list) ) ,
244
+ None => {
245
+ let comma = if add_comma { "," } else { "" } ;
246
+ Some ( format ! ( "({}{})" , list, comma) )
247
+ }
248
+ }
249
+ }
250
+ }
0 commit comments