@@ -6,7 +6,7 @@ use syntax::{ast, visit};
66
77use crate :: attr:: * ;
88use crate :: comment:: { CodeCharKind , CommentCodeSlices } ;
9- use crate :: config:: file_lines:: FileName ;
9+ use crate :: config:: file_lines:: LineRange ;
1010use crate :: config:: { BraceStyle , Config } ;
1111use crate :: items:: {
1212 format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item,
@@ -89,6 +89,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
8989 Shape :: indented ( self . block_indent , self . config )
9090 }
9191
92+ fn next_span ( & self , hi : BytePos ) -> Span {
93+ mk_sp ( self . last_pos , hi)
94+ }
95+
9296 fn visit_stmt ( & mut self , stmt : & Stmt < ' _ > ) {
9397 debug ! (
9498 "visit_stmt: {:?} {:?}" ,
@@ -132,31 +136,19 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
132136 }
133137 }
134138
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 (
136142 & mut self ,
137143 b : & ast:: Block ,
138144 inner_attrs : Option < & [ ast:: Attribute ] > ,
139- has_braces : bool ,
140145 ) {
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-
154146 if let Some ( first_stmt) = b. stmts . first ( ) {
155147 let hi = inner_attrs
156148 . and_then ( |attrs| inner_attributes ( attrs) . first ( ) . map ( |attr| attr. span . lo ( ) ) )
157149 . 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 ) ;
160152 let len = CommentCodeSlices :: new ( snippet)
161153 . nth ( 0 )
162154 . and_then ( |( kind, _, s) | {
@@ -170,19 +162,57 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
170162 self . last_pos = self . last_pos + BytePos :: from_usize ( len) ;
171163 }
172164 }
165+ }
173166
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+ }
180192
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 ) ;
186216 }
187217
188218 self . walk_block_stmts ( b) ;
@@ -195,36 +225,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
195225 }
196226 }
197227
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 ;
220234 }
221235
236+ let remove_len = BytePos :: from_usize (
237+ self . trimmed_spaces_width_before_closing_brace ( b, brace_compensation) ,
238+ ) ;
222239 let unindent_comment = self . is_if_else_block && !b. stmts . is_empty ( ) && {
223240 let end_pos = source ! ( self , b. span) . hi ( ) - brace_compensation - remove_len;
224241 let snippet = self . snippet ( mk_sp ( self . last_pos , end_pos) ) ;
225242 snippet. contains ( "//" ) || snippet. contains ( "/*" )
226243 } ;
227- // FIXME: we should compress any newlines here to just one
228244 if unindent_comment {
229245 self . block_indent = self . block_indent . block_unindent ( self . config ) ;
230246 }
@@ -234,7 +250,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
234250 if unindent_comment {
235251 self . block_indent = self . block_indent . block_indent ( self . config ) ;
236252 }
237- self . close_block ( unindent_comment, b. span ) ;
253+ self . close_block ( unindent_comment, self . next_span ( b. span . hi ( ) ) ) ;
238254 self . last_pos = source ! ( self , b. span) . hi ( ) ;
239255 }
240256
@@ -243,12 +259,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
243259 // The closing brace itself, however, should be indented at a shallower
244260 // level.
245261 fn close_block ( & mut self , unindent_comment : bool , span : Span ) {
246- let file_name: FileName = self . source_map . span_to_filename ( span) . into ( ) ;
247262 let skip_this_line = !self
248263 . config
249264 . 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 {
252269 let total_len = self . buffer . len ( ) ;
253270 let chars_too_many = if unindent_comment {
254271 0
@@ -271,8 +288,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
271288 self . buffer . push_str ( "\n " ) ;
272289 }
273290 }
291+ self . push_str ( "}" ) ;
274292 }
275- self . push_str ( "}" ) ;
276293 self . block_indent = self . block_indent . block_unindent ( self . config ) ;
277294 }
278295
@@ -800,8 +817,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
800817 self . block_indent = self . block_indent . block_indent ( self . config ) ;
801818 self . visit_attrs ( attrs, ast:: AttrStyle :: Inner ) ;
802819 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) ;
805823 }
806824 self . last_pos = source ! ( self , m. inner) . hi ( ) ;
807825 } else {
@@ -823,9 +841,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
823841 pub ( crate ) fn skip_empty_lines ( & mut self , end_pos : BytePos ) {
824842 while let Some ( pos) = self
825843 . snippet_provider
826- . opt_span_after ( mk_sp ( self . last_pos , end_pos) , "\n " )
844+ . opt_span_after ( self . next_span ( end_pos) , "\n " )
827845 {
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) ) {
829847 if snippet. trim ( ) . is_empty ( ) {
830848 self . last_pos = pos;
831849 } else {
0 commit comments