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