@@ -6,7 +6,7 @@ use syntax::{ast, visit};
6
6
7
7
use crate :: attr:: * ;
8
8
use crate :: comment:: { CodeCharKind , CommentCodeSlices } ;
9
- use crate :: config:: file_lines:: FileName ;
9
+ use crate :: config:: file_lines:: LineRange ;
10
10
use crate :: config:: { BraceStyle , Config } ;
11
11
use crate :: items:: {
12
12
format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item,
@@ -89,6 +89,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
89
89
Shape :: indented ( self . block_indent , self . config )
90
90
}
91
91
92
+ fn next_span ( & self , hi : BytePos ) -> Span {
93
+ mk_sp ( self . last_pos , hi)
94
+ }
95
+
92
96
fn visit_stmt ( & mut self , stmt : & Stmt < ' _ > ) {
93
97
debug ! (
94
98
"visit_stmt: {:?} {:?}" ,
@@ -132,31 +136,19 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
132
136
}
133
137
}
134
138
135
- pub ( crate ) fn visit_block (
139
+ /// Remove spaces between the opening brace and the first statement or the inner attribute
140
+ /// of the block.
141
+ fn trim_spaces_after_opening_brace (
136
142
& mut self ,
137
143
b : & ast:: Block ,
138
144
inner_attrs : Option < & [ ast:: Attribute ] > ,
139
- has_braces : bool ,
140
145
) {
141
- debug ! (
142
- "visit_block: {:?} {:?}" ,
143
- self . source_map. lookup_char_pos( b. span. lo( ) ) ,
144
- self . source_map. lookup_char_pos( b. span. hi( ) )
145
- ) ;
146
-
147
- // Check if this block has braces.
148
- let brace_compensation = BytePos ( if has_braces { 1 } else { 0 } ) ;
149
-
150
- self . last_pos = self . last_pos + brace_compensation;
151
- self . block_indent = self . block_indent . block_indent ( self . config ) ;
152
- self . push_str ( "{" ) ;
153
-
154
146
if let Some ( first_stmt) = b. stmts . first ( ) {
155
147
let hi = inner_attrs
156
148
. and_then ( |attrs| inner_attributes ( attrs) . first ( ) . map ( |attr| attr. span . lo ( ) ) )
157
149
. unwrap_or_else ( || first_stmt. span ( ) . lo ( ) ) ;
158
-
159
- let snippet = self . snippet ( mk_sp ( self . last_pos , hi ) ) ;
150
+ let missing_span = self . next_span ( hi ) ;
151
+ let snippet = self . snippet ( missing_span ) ;
160
152
let len = CommentCodeSlices :: new ( snippet)
161
153
. nth ( 0 )
162
154
. and_then ( |( kind, _, s) | {
@@ -170,19 +162,57 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
170
162
self . last_pos = self . last_pos + BytePos :: from_usize ( len) ;
171
163
}
172
164
}
165
+ }
173
166
174
- // Format inner attributes if available.
175
- let skip_rewrite = if let Some ( attrs) = inner_attrs {
176
- self . visit_attrs ( attrs, ast:: AttrStyle :: Inner )
177
- } else {
178
- false
179
- } ;
167
+ /// Returns the total length of the spaces which should be trimmed between the last statement
168
+ /// and the closing brace of the block.
169
+ fn trimmed_spaces_width_before_closing_brace (
170
+ & mut self ,
171
+ b : & ast:: Block ,
172
+ brace_compensation : BytePos ,
173
+ ) -> usize {
174
+ match b. stmts . last ( ) {
175
+ None => 0 ,
176
+ Some ( ..) => {
177
+ let span_after_last_stmt = self . next_span ( b. span . hi ( ) - brace_compensation) ;
178
+ let missing_snippet = self . snippet ( span_after_last_stmt) ;
179
+ CommentCodeSlices :: new ( missing_snippet)
180
+ . last ( )
181
+ . and_then ( |( kind, _, s) | {
182
+ if kind == CodeCharKind :: Normal && s. trim ( ) . is_empty ( ) {
183
+ Some ( s. len ( ) )
184
+ } else {
185
+ None
186
+ }
187
+ } )
188
+ . unwrap_or ( 0 )
189
+ }
190
+ }
191
+ }
180
192
181
- if skip_rewrite {
182
- self . push_rewrite ( b. span , None ) ;
183
- self . close_block ( false , b. span ) ;
184
- self . last_pos = source ! ( self , b. span) . hi ( ) ;
185
- return ;
193
+ pub ( crate ) fn visit_block (
194
+ & mut self ,
195
+ b : & ast:: Block ,
196
+ inner_attrs : Option < & [ ast:: Attribute ] > ,
197
+ has_braces : bool ,
198
+ ) {
199
+ debug ! (
200
+ "visit_block: {:?} {:?}" ,
201
+ self . source_map. lookup_char_pos( b. span. lo( ) ) ,
202
+ self . source_map. lookup_char_pos( b. span. hi( ) )
203
+ ) ;
204
+
205
+ // Check if this block has braces.
206
+ let brace_compensation = BytePos ( if has_braces { 1 } else { 0 } ) ;
207
+
208
+ self . last_pos = self . last_pos + brace_compensation;
209
+ self . block_indent = self . block_indent . block_indent ( self . config ) ;
210
+ self . push_str ( "{" ) ;
211
+ self . trim_spaces_after_opening_brace ( b, inner_attrs) ;
212
+
213
+ // Format inner attributes if available.
214
+ if let Some ( attrs) = inner_attrs {
215
+ self . visit_attrs ( attrs, ast:: AttrStyle :: Inner ) ;
186
216
}
187
217
188
218
self . walk_block_stmts ( b) ;
@@ -195,36 +225,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
195
225
}
196
226
}
197
227
198
- let mut remove_len = BytePos ( 0 ) ;
199
- if let Some ( stmt) = b. stmts . last ( ) {
200
- let span_after_last_stmt = mk_sp (
201
- stmt. span . hi ( ) ,
202
- source ! ( self , b. span) . hi ( ) - brace_compensation,
203
- ) ;
204
- // if the span is outside of a file_lines range, then do not try to remove anything
205
- if !out_of_file_lines_range ! ( self , span_after_last_stmt) {
206
- let snippet = self . snippet ( span_after_last_stmt) ;
207
- let len = CommentCodeSlices :: new ( snippet)
208
- . last ( )
209
- . and_then ( |( kind, _, s) | {
210
- if kind == CodeCharKind :: Normal && s. trim ( ) . is_empty ( ) {
211
- Some ( s. len ( ) )
212
- } else {
213
- None
214
- }
215
- } ) ;
216
- if let Some ( len) = len {
217
- remove_len = BytePos :: from_usize ( len) ;
218
- }
219
- }
228
+ let missing_span = self . next_span ( b. span . hi ( ) ) ;
229
+ if out_of_file_lines_range ! ( self , missing_span) {
230
+ self . push_str ( self . snippet ( missing_span) ) ;
231
+ self . block_indent = self . block_indent . block_unindent ( self . config ) ;
232
+ self . last_pos = source ! ( self , b. span) . hi ( ) ;
233
+ return ;
220
234
}
221
235
236
+ let remove_len = BytePos :: from_usize (
237
+ self . trimmed_spaces_width_before_closing_brace ( b, brace_compensation) ,
238
+ ) ;
222
239
let unindent_comment = self . is_if_else_block && !b. stmts . is_empty ( ) && {
223
240
let end_pos = source ! ( self , b. span) . hi ( ) - brace_compensation - remove_len;
224
241
let snippet = self . snippet ( mk_sp ( self . last_pos , end_pos) ) ;
225
242
snippet. contains ( "//" ) || snippet. contains ( "/*" )
226
243
} ;
227
- // FIXME: we should compress any newlines here to just one
228
244
if unindent_comment {
229
245
self . block_indent = self . block_indent . block_unindent ( self . config ) ;
230
246
}
@@ -234,7 +250,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
234
250
if unindent_comment {
235
251
self . block_indent = self . block_indent . block_indent ( self . config ) ;
236
252
}
237
- self . close_block ( unindent_comment, b. span ) ;
253
+ self . close_block ( unindent_comment, self . next_span ( b. span . hi ( ) ) ) ;
238
254
self . last_pos = source ! ( self , b. span) . hi ( ) ;
239
255
}
240
256
@@ -243,12 +259,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
243
259
// The closing brace itself, however, should be indented at a shallower
244
260
// level.
245
261
fn close_block ( & mut self , unindent_comment : bool , span : Span ) {
246
- let file_name: FileName = self . source_map . span_to_filename ( span) . into ( ) ;
247
262
let skip_this_line = !self
248
263
. config
249
264
. file_lines ( )
250
- . contains_line ( & file_name, self . line_number ) ;
251
- if !skip_this_line {
265
+ . contains ( & LineRange :: from_span ( self . source_map , span) ) ;
266
+ if skip_this_line {
267
+ self . push_str ( self . snippet ( span) ) ;
268
+ } else {
252
269
let total_len = self . buffer . len ( ) ;
253
270
let chars_too_many = if unindent_comment {
254
271
0
@@ -271,8 +288,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
271
288
self . buffer . push_str ( "\n " ) ;
272
289
}
273
290
}
291
+ self . push_str ( "}" ) ;
274
292
}
275
- self . push_str ( "}" ) ;
276
293
self . block_indent = self . block_indent . block_unindent ( self . config ) ;
277
294
}
278
295
@@ -800,8 +817,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
800
817
self . block_indent = self . block_indent . block_indent ( self . config ) ;
801
818
self . visit_attrs ( attrs, ast:: AttrStyle :: Inner ) ;
802
819
self . walk_mod_items ( m) ;
803
- self . format_missing_with_indent ( source ! ( self , m. inner) . hi ( ) - BytePos ( 1 ) ) ;
804
- self . close_block ( false , m. inner ) ;
820
+ let missing_span = mk_sp ( source ! ( self , m. inner) . hi ( ) - BytePos ( 1 ) , m. inner . hi ( ) ) ;
821
+ self . format_missing_with_indent ( missing_span. lo ( ) ) ;
822
+ self . close_block ( false , missing_span) ;
805
823
}
806
824
self . last_pos = source ! ( self , m. inner) . hi ( ) ;
807
825
} else {
@@ -823,9 +841,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
823
841
pub ( crate ) fn skip_empty_lines ( & mut self , end_pos : BytePos ) {
824
842
while let Some ( pos) = self
825
843
. snippet_provider
826
- . opt_span_after ( mk_sp ( self . last_pos , end_pos) , "\n " )
844
+ . opt_span_after ( self . next_span ( end_pos) , "\n " )
827
845
{
828
- if let Some ( snippet) = self . opt_snippet ( mk_sp ( self . last_pos , pos) ) {
846
+ if let Some ( snippet) = self . opt_snippet ( self . next_span ( pos) ) {
829
847
if snippet. trim ( ) . is_empty ( ) {
830
848
self . last_pos = pos;
831
849
} else {
0 commit comments