diff --git a/src/expr.rs b/src/expr.rs index c1d5e8ccc39..35e1e432733 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -914,7 +914,7 @@ fn rewrite_block_with_visitor( ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo, } - visitor.visit_block(block); + visitor.visit_block(block, None); Some(format!("{}{}", prefix, visitor.buffer)) } diff --git a/src/items.rs b/src/items.rs index 087b5615f02..9c3fb86f73e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -640,6 +640,7 @@ pub fn format_impl( visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = item.span.lo + BytePos(open_pos as u32); + visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); for item in items { visitor.visit_impl_item(item); } diff --git a/src/lib.rs b/src/lib.rs index bd611202fb7..5647e6df5e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -554,17 +554,24 @@ fn format_ast( if skip_children && path.as_path() != main_file { continue; } - let path = path.to_str().unwrap(); + let path_str = path.to_str().unwrap(); if config.verbose() { - println!("Formatting {}", path); + println!("Formatting {}", path_str); } { let mut visitor = FmtVisitor::from_codemap(parse_session, config); - visitor.format_separate_mod(module); + let filemap = visitor.codemap.lookup_char_pos(module.inner.lo).file; + // Format inner attributes if available. + if !krate.attrs.is_empty() && path == main_file { + visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner); + } else { + visitor.last_pos = filemap.start_pos; + } + visitor.format_separate_mod(module, &*filemap); - has_diff |= after_file(path, &mut visitor.buffer)?; + has_diff |= after_file(path_str, &mut visitor.buffer)?; - result.push((path.to_owned(), visitor.buffer)); + result.push((path_str.to_owned(), visitor.buffer)); } // Reset the error count. if parse_session.span_diagnostic.has_errors() { diff --git a/src/visitor.rs b/src/visitor.rs index 77a39f9efc3..0f7005e2856 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -12,7 +12,7 @@ use strings::string_buffer::StringBuffer; use syntax::{ast, ptr, visit}; -use syntax::codemap::{BytePos, CodeMap, Span}; +use syntax::codemap::{self, BytePos, CodeMap, Span}; use syntax::parse::ParseSess; use {Indent, Shape}; @@ -128,7 +128,7 @@ fn visit_stmt(&mut self, stmt: &ast::Stmt) { } } - pub fn visit_block(&mut self, b: &ast::Block) { + pub fn visit_block(&mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribute]>) { debug!( "visit_block: {:?} {:?}", self.codemap.lookup_char_pos(b.span.lo), @@ -144,6 +144,11 @@ pub fn visit_block(&mut self, b: &ast::Block) { self.block_indent = self.block_indent.block_indent(self.config); self.buffer.push_str("{"); + // Format inner attributes if available. + if let Some(attrs) = inner_attrs { + self.visit_attrs(attrs, ast::AttrStyle::Inner); + } + for stmt in &b.stmts { self.visit_stmt(stmt) } @@ -201,6 +206,7 @@ fn visit_fn( s: Span, _: ast::NodeId, defaultness: ast::Defaultness, + inner_attrs: Option<&[ast::Attribute]>, ) { let indent = self.block_indent; let block; @@ -254,7 +260,7 @@ fn visit_fn( } self.last_pos = source!(self, block.span).lo; - self.visit_block(block) + self.visit_block(block, inner_attrs) } pub fn visit_item(&mut self, item: &ast::Item) { @@ -262,6 +268,7 @@ pub fn visit_item(&mut self, item: &ast::Item) { // complex in the module case. It is complex because the module could be // in a separate file and there might be attributes in both files, but // the AST lumps them all together. + let mut attrs = item.attrs.clone(); match item.node { ast::ItemKind::Mod(ref m) => { let outer_file = self.codemap.lookup_char_pos(item.span.lo).file; @@ -269,7 +276,7 @@ pub fn visit_item(&mut self, item: &ast::Item) { if outer_file.name == inner_file.name { // Module is inline, in this case we treat modules like any // other item. - if self.visit_attrs(&item.attrs) { + if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { self.push_rewrite(item.span, None); return; } @@ -279,7 +286,7 @@ pub fn visit_item(&mut self, item: &ast::Item) { } else { // Module is not inline and should not be skipped. We want // to process only the attributes in the current file. - let attrs = item.attrs + let filterd_attrs = item.attrs .iter() .filter_map(|a| { let attr_file = self.codemap.lookup_char_pos(a.span.lo).file; @@ -292,10 +299,11 @@ pub fn visit_item(&mut self, item: &ast::Item) { .collect::>(); // Assert because if we should skip it should be caught by // the above case. - assert!(!self.visit_attrs(&attrs)); + assert!(!self.visit_attrs(&filterd_attrs, ast::AttrStyle::Outer)); + attrs = filterd_attrs; } } - _ => if self.visit_attrs(&item.attrs) { + _ => if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { self.push_rewrite(item.span, None); return; }, @@ -361,7 +369,7 @@ pub fn visit_item(&mut self, item: &ast::Item) { } ast::ItemKind::Mod(ref module) => { self.format_missing_with_indent(source!(self, item.span).lo); - self.format_mod(module, &item.vis, item.span, item.ident); + self.format_mod(module, &item.vis, item.span, item.ident, &attrs); } ast::ItemKind::Mac(ref mac) => { self.visit_mac(mac, Some(item.ident), MacroPosition::Item); @@ -416,6 +424,7 @@ pub fn visit_item(&mut self, item: &ast::Item) { item.span, item.id, ast::Defaultness::Final, + Some(&item.attrs), ) } ast::ItemKind::Ty(ref ty, ref generics) => { @@ -457,7 +466,7 @@ pub fn visit_item(&mut self, item: &ast::Item) { } pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { - if self.visit_attrs(&ti.attrs) { + if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { self.push_rewrite(ti.span, None); return; } @@ -489,6 +498,7 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { ti.span, ti.id, ast::Defaultness::Final, + Some(&ti.attrs), ); } ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => { @@ -508,7 +518,7 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { } pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { - if self.visit_attrs(&ii.attrs) { + if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { self.push_rewrite(ii.span, None); return; } @@ -521,6 +531,7 @@ pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { ii.span, ii.id, ii.defaultness, + Some(&ii.attrs), ); } ast::ImplItemKind::Const(ref ty, ref expr) => { @@ -655,7 +666,14 @@ fn walk_mod_items(&mut self, m: &ast::Mod) { } } - fn format_mod(&mut self, m: &ast::Mod, vis: &ast::Visibility, s: Span, ident: ast::Ident) { + fn format_mod( + &mut self, + m: &ast::Mod, + vis: &ast::Visibility, + s: Span, + ident: ast::Ident, + attrs: &[ast::Attribute], + ) { // Decide whether this is an inline mod or an external mod. let local_file_name = self.codemap.span_to_filename(s); let inner_span = source!(self, m.inner); @@ -681,6 +699,7 @@ fn format_mod(&mut self, m: &ast::Mod, vis: &ast::Visibility, s: Span, ident: as } else { self.last_pos = mod_lo; self.block_indent = self.block_indent.block_indent(self.config); + self.visit_attrs(attrs, ast::AttrStyle::Inner); self.walk_mod_items(m); self.format_missing_with_indent(source!(self, m.inner).hi - BytePos(1)); self.close_block(false); @@ -692,9 +711,7 @@ fn format_mod(&mut self, m: &ast::Mod, vis: &ast::Visibility, s: Span, ident: as } } - pub fn format_separate_mod(&mut self, m: &ast::Mod) { - let filemap = self.codemap.lookup_char_pos(m.inner.lo).file; - self.last_pos = filemap.start_pos; + pub fn format_separate_mod(&mut self, m: &ast::Mod, filemap: &codemap::FileMap) { self.block_indent = Indent::empty(); self.walk_mod_items(m); self.format_missing_with_indent(filemap.end_pos);