diff --git a/src/lib.rs b/src/lib.rs index 5647e6df5e2..e1017fab959 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,7 @@ use config::Config; use filemap::FileMap; use issues::{BadIssueSeeker, Issue}; -use utils::mk_sp; +use utils::{mk_sp, outer_attributes}; use visitor::FmtVisitor; pub use self::summary::Summary; @@ -81,13 +81,33 @@ pub trait Spanned { fn span(&self) -> Span; } +macro_rules! span_with_attrs_lo_hi { + ($this:ident, $lo:expr, $hi:expr) => { + { + let attrs = outer_attributes(&$this.attrs); + if attrs.is_empty() { + mk_sp($lo, $hi) + } else { + mk_sp(attrs[0].span.lo, $hi) + } + } + } +} +macro_rules! span_with_attrs { + ($this:ident) => { + span_with_attrs_lo_hi!($this, $this.span.lo, $this.span.hi) + } +} + impl Spanned for ast::Expr { fn span(&self) -> Span { - if self.attrs.is_empty() { - self.span - } else { - mk_sp(self.attrs[0].span.lo, self.span.hi) - } + span_with_attrs!(self) + } +} + +impl Spanned for ast::Item { + fn span(&self) -> Span { + span_with_attrs!(self) } } @@ -117,12 +137,7 @@ fn span(&self) -> Span { impl Spanned for ast::Arm { fn span(&self) -> Span { - let hi = self.body.span.hi; - if self.attrs.is_empty() { - mk_sp(self.pats[0].span.lo, hi) - } else { - mk_sp(self.attrs[0].span.lo, hi) - } + span_with_attrs_lo_hi!(self, self.pats[0].span.lo, self.body.span.hi) } } @@ -138,23 +153,13 @@ fn span(&self) -> Span { impl Spanned for ast::StructField { fn span(&self) -> Span { - if self.attrs.is_empty() { - mk_sp(self.span.lo, self.ty.span.hi) - } else { - // Include attributes and doc comments, if present - mk_sp(self.attrs[0].span.lo, self.ty.span.hi) - } + span_with_attrs_lo_hi!(self, self.span.lo, self.ty.span.hi) } } impl Spanned for ast::Field { fn span(&self) -> Span { - let lo = if self.attrs.is_empty() { - self.span.lo - } else { - self.attrs[0].span.lo - }; - mk_sp(lo, self.span.hi) + span_with_attrs!(self) } } diff --git a/src/utils.rs b/src/utils.rs index d0917721898..c0861b8da20 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -97,6 +97,25 @@ pub fn format_abi(abi: abi::Abi, explicit_abi: bool) -> String { } } +#[inline] +pub fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec { + attrs + .iter() + .filter(|a| a.style == style) + .cloned() + .collect::>() +} + +#[inline] +pub fn inner_attributes(attrs: &[ast::Attribute]) -> Vec { + filter_attributes(attrs, ast::AttrStyle::Inner) +} + +#[inline] +pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec { + filter_attributes(attrs, ast::AttrStyle::Outer) +} + // The width of the first line in s. #[inline] pub fn first_line_width(s: &str) -> usize { diff --git a/src/visitor.rs b/src/visitor.rs index bc3126615d3..ef0ff1d52db 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -15,7 +15,7 @@ use syntax::codemap::{self, BytePos, CodeMap, Span}; use syntax::parse::ParseSess; -use {Indent, Shape}; +use {Indent, Shape, Spanned}; use codemap::{LineRangeUtils, SpanUtils}; use comment::{contains_comment, FindUncommented}; use comment::rewrite_comment; @@ -36,19 +36,6 @@ fn is_use_item(item: &ast::Item) -> bool { } } -fn item_bound(item: &ast::Item) -> Span { - item.attrs.iter().map(|attr| attr.span).fold( - item.span, - |bound, span| { - Span { - lo: cmp::min(bound.lo, span.lo), - hi: cmp::max(bound.hi, span.hi), - ctxt: span.ctxt, - } - }, - ) -} - pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, @@ -93,7 +80,7 @@ fn visit_stmt(&mut self, stmt: &ast::Stmt) { let span = if expr.attrs.is_empty() { stmt.span } else { - mk_sp(expr.attrs[0].span.lo, stmt.span.hi) + mk_sp(expr.span().lo, stmt.span.hi) }; self.push_rewrite(span, rewrite) } @@ -105,7 +92,7 @@ fn visit_stmt(&mut self, stmt: &ast::Stmt) { let span = if expr.attrs.is_empty() { stmt.span } else { - mk_sp(expr.attrs[0].span.lo, stmt.span.hi) + mk_sp(expr.span().lo, stmt.span.hi) }; self.push_rewrite(span, rewrite) } @@ -648,12 +635,12 @@ fn walk_mod_items(&mut self, m: &ast::Mod) { // next item for output. if self.config.reorder_imports() && is_use_item(&*items_left[0]) { let reorder_imports_in_group = self.config.reorder_imports_in_group(); - let mut last = self.codemap.lookup_line_range(item_bound(&items_left[0])); + let mut last = self.codemap.lookup_line_range(items_left[0].span()); let use_item_length = items_left .iter() .take_while(|ppi| { is_use_item(&***ppi) && (!reorder_imports_in_group || { - let current = self.codemap.lookup_line_range(item_bound(&ppi)); + let current = self.codemap.lookup_line_range(ppi.span()); let in_same_group = current.lo < last.hi + 2; last = current; in_same_group