@@ -15,20 +15,32 @@ use lists::{format_item_list, itemize_list};
15
15
use expr:: { rewrite_unary_prefix, rewrite_pair, rewrite_tuple} ;
16
16
use types:: rewrite_path;
17
17
18
- use syntax:: ast:: { BindingMode , Pat , Pat_ } ;
18
+ use syntax:: ast:: { BindingMode , Pat , Pat_ , FieldPat } ;
19
19
20
- // FIXME(#18): implement pattern formatting.
21
20
impl Rewrite for Pat {
22
21
fn rewrite ( & self , context : & RewriteContext , width : usize , offset : Indent ) -> Option < String > {
23
22
match self . node {
24
23
Pat_ :: PatBox ( ref pat) => rewrite_unary_prefix ( context, "box " , & * * pat, width, offset) ,
25
- Pat_ :: PatIdent ( binding_mode, ident, None ) => {
24
+ Pat_ :: PatIdent ( binding_mode, ident, ref sub_pat ) => {
26
25
let ( prefix, mutability) = match binding_mode {
27
26
BindingMode :: BindByRef ( mutability) => ( "ref " , mutability) ,
28
27
BindingMode :: BindByValue ( mutability) => ( "" , mutability) ,
29
28
} ;
30
29
let mut_infix = format_mutability ( mutability) ;
31
- let result = format ! ( "{}{}{}" , prefix, mut_infix, ident. node) ;
30
+ let id_str = ident. node . to_string ( ) ;
31
+
32
+ let sub_pat = match * sub_pat {
33
+ Some ( ref p) => {
34
+ // 3 - ` @ `.
35
+ let width = try_opt ! ( width. checked_sub( prefix. len( ) + mut_infix. len( ) +
36
+ id_str. len( ) +
37
+ 3 ) ) ;
38
+ format ! ( " @ {}" , try_opt!( p. rewrite( context, width, offset) ) )
39
+ }
40
+ None => "" . to_owned ( ) ,
41
+ } ;
42
+
43
+ let result = format ! ( "{}{}{}{}" , prefix, mut_infix, id_str, sub_pat) ;
32
44
wrap_str ( result, context. config . max_width , width, offset)
33
45
}
34
46
Pat_ :: PatWild => {
@@ -55,39 +67,106 @@ impl Rewrite for Pat {
55
67
width,
56
68
offset)
57
69
}
58
- Pat_ :: PatEnum ( ref path, Some ( ref pat_vec) ) => {
59
- let path_str = try_opt ! ( :: types:: rewrite_path( context,
60
- true ,
61
- None ,
62
- path,
63
- width,
64
- offset) ) ;
70
+ Pat_ :: PatEnum ( ref path, ref pat_vec) => {
71
+ let path_str = try_opt ! ( rewrite_path( context, true , None , path, width, offset) ) ;
65
72
66
- if pat_vec. is_empty ( ) {
67
- Some ( path_str)
68
- } else {
69
- // 1 = (
70
- let width = try_opt ! ( width. checked_sub( path_str. len( ) + 1 ) ) ;
71
- let offset = offset + path_str. len ( ) + 1 ;
72
- let items = itemize_list ( context. codemap ,
73
- pat_vec. iter ( ) ,
74
- ")" ,
75
- |item| item. span . lo ,
76
- |item| item. span . hi ,
77
- |item| item. rewrite ( context, width, offset) ,
78
- span_after ( self . span , "(" , context. codemap ) ,
79
- self . span . hi ) ;
80
- Some ( format ! ( "{}({})" ,
81
- path_str,
82
- try_opt!( format_item_list( items, width, offset, context. config) ) ) )
73
+ match * pat_vec {
74
+ Some ( ref pat_vec) => {
75
+ if pat_vec. is_empty ( ) {
76
+ Some ( path_str)
77
+ } else {
78
+ // 1 = (
79
+ let width = try_opt ! ( width. checked_sub( path_str. len( ) + 1 ) ) ;
80
+ let offset = offset + path_str. len ( ) + 1 ;
81
+ let items = itemize_list ( context. codemap ,
82
+ pat_vec. iter ( ) ,
83
+ ")" ,
84
+ |item| item. span . lo ,
85
+ |item| item. span . hi ,
86
+ |item| item. rewrite ( context, width, offset) ,
87
+ span_after ( self . span , "(" , context. codemap ) ,
88
+ self . span . hi ) ;
89
+ Some ( format ! ( "{}({})" ,
90
+ path_str,
91
+ try_opt!( format_item_list( items,
92
+ width,
93
+ offset,
94
+ context. config) ) ) )
95
+ }
96
+ }
97
+ None => Some ( format ! ( "{}(..)" , path_str) ) ,
83
98
}
84
99
}
85
100
Pat_ :: PatLit ( ref expr) => expr. rewrite ( context, width, offset) ,
86
- // FIXME(#8): format remaining pattern variants.
87
- Pat_ :: PatIdent ( _, _, Some ( ..) ) |
88
- Pat_ :: PatEnum ( _, None ) |
89
- Pat_ :: PatStruct ( ..) |
90
- Pat_ :: PatVec ( ..) |
101
+ Pat_ :: PatVec ( ref prefix, ref slice_pat, ref suffix) => {
102
+ // Rewrite all the sub-patterns.
103
+ let prefix = prefix. iter ( ) . map ( |p| p. rewrite ( context, width, offset) ) ;
104
+ let slice_pat = slice_pat. as_ref ( ) . map ( |p| {
105
+ Some ( format ! ( "{}.." , try_opt!( p. rewrite( context, width, offset) ) ) )
106
+ } ) ;
107
+ let suffix = suffix. iter ( ) . map ( |p| p. rewrite ( context, width, offset) ) ;
108
+
109
+ // Munge them together.
110
+ let pats: Option < Vec < String > > = prefix. chain ( slice_pat. into_iter ( ) )
111
+ . chain ( suffix)
112
+ . collect ( ) ;
113
+
114
+ // Check that all the rewrites succeeded, and if not return None.
115
+ let pats = try_opt ! ( pats) ;
116
+
117
+ // Unwrap all the sub-strings and join them with commas.
118
+ let result = format ! ( "[{}]" , pats. join( ", " ) ) ;
119
+ wrap_str ( result, context. config . max_width , width, offset)
120
+ }
121
+ Pat_ :: PatStruct ( ref path, ref fields, elipses) => {
122
+ let path = try_opt ! ( rewrite_path( context, true , None , path, width, offset) ) ;
123
+
124
+ let ( elipses_str, terminator) = if elipses {
125
+ ( ", .." , ".." )
126
+ } else {
127
+ ( "" , "}" )
128
+ } ;
129
+
130
+ // 5 = `{` plus space before and after plus `}` plus space before.
131
+ let budget = try_opt ! ( width. checked_sub( path. len( ) + 5 + elipses_str. len( ) ) ) ;
132
+ // FIXME Using visual indenting, should use block or visual to match
133
+ // struct lit preference (however, in practice I think it is rare
134
+ // for struct patterns to be multi-line).
135
+ // 3 = `{` plus space before and after.
136
+ let offset = offset + path. len ( ) + 3 ;
137
+
138
+ let items = itemize_list ( context. codemap ,
139
+ fields. iter ( ) ,
140
+ terminator,
141
+ |f| f. span . lo ,
142
+ |f| f. span . hi ,
143
+ |f| f. node . rewrite ( context, budget, offset) ,
144
+ span_after ( self . span , "{" , context. codemap ) ,
145
+ self . span . hi ) ;
146
+ let mut field_string = try_opt ! ( format_item_list( items,
147
+ budget,
148
+ offset,
149
+ context. config) ) ;
150
+ if elipses {
151
+ if field_string. contains ( '\n' ) {
152
+ field_string. push_str ( ",\n " ) ;
153
+ field_string. push_str ( & offset. to_string ( context. config ) ) ;
154
+ field_string. push_str ( ".." ) ;
155
+ } else {
156
+ if field_string. len ( ) > 0 {
157
+ field_string. push_str ( ", " ) ;
158
+ }
159
+ field_string. push_str ( ".." ) ;
160
+ }
161
+ }
162
+
163
+ if field_string. is_empty ( ) {
164
+ Some ( format ! ( "{} {{}}" , path) )
165
+ } else {
166
+ Some ( format ! ( "{} {{ {} }}" , path, field_string) )
167
+ }
168
+ }
169
+ // FIXME(#819) format pattern macros.
91
170
Pat_ :: PatMac ( ..) => {
92
171
wrap_str ( context. snippet ( self . span ) ,
93
172
context. config . max_width ,
@@ -97,3 +176,17 @@ impl Rewrite for Pat {
97
176
}
98
177
}
99
178
}
179
+
180
+ impl Rewrite for FieldPat {
181
+ fn rewrite ( & self , context : & RewriteContext , width : usize , offset : Indent ) -> Option < String > {
182
+ let pat = self . pat . rewrite ( context, width, offset) ;
183
+ if self . is_shorthand {
184
+ pat
185
+ } else {
186
+ wrap_str ( format ! ( "{}: {}" , self . ident. to_string( ) , try_opt!( pat) ) ,
187
+ context. config . max_width ,
188
+ width,
189
+ offset)
190
+ }
191
+ }
192
+ }
0 commit comments