about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEvgenii <evgeniy@nspcc.ru>2019-02-06 09:34:50 +0300
committerEvgenii <evgeniy@nspcc.ru>2019-02-06 10:05:51 +0300
commitda2d8a4c5797b3d1e2139a1ec0638e1b0546fd0c (patch)
tree84f20890621adecc5984b914a7fecb893be18c60 /src
parentaec0a7c99952649e8fbf9bf5f4609af470c17c83 (diff)
calculate statement first line properly
Diffstat (limited to 'src')
-rw-r--r--src/attr.rs12
-rw-r--r--src/visitor.rs28
2 files changed, 30 insertions, 10 deletions
diff --git a/src/attr.rs b/src/attr.rs
index 465c17fe2a0..52b55a9a175 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -34,6 +34,18 @@ pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] {
     }
 }
 
+pub fn get_span_without_attrs(stmt: &ast::Stmt) -> Span {
+    match stmt.node {
+        ast::StmtKind::Local(ref local) => local.span,
+        ast::StmtKind::Item(ref item) => item.span,
+        ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span,
+        ast::StmtKind::Mac(ref mac) => {
+            let (ref mac, _, _) = **mac;
+            mac.span
+        }
+    }
+}
+
 /// Returns attributes that are within `outer_span`.
 pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec<ast::Attribute> {
     attrs
diff --git a/src/visitor.rs b/src/visitor.rs
index 029905f7e80..41309f5272e 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -113,7 +113,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => {
                 let attrs = get_attrs_from_stmt(stmt);
                 if contains_skip(attrs) {
-                    self.push_skipped_with_span(attrs, stmt.span());
+                    self.push_skipped_with_span(attrs, stmt.span(), get_span_without_attrs(stmt));
                 } else {
                     let shape = self.shape();
                     let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape));
@@ -123,7 +123,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             ast::StmtKind::Mac(ref mac) => {
                 let (ref mac, _macro_style, ref attrs) = **mac;
                 if self.visit_attrs(attrs, ast::AttrStyle::Outer) {
-                    self.push_skipped_with_span(attrs, stmt.span());
+                    self.push_skipped_with_span(attrs, stmt.span(), get_span_without_attrs(stmt));
                 } else {
                     self.visit_mac(mac, None, MacroPosition::Statement);
                 }
@@ -331,14 +331,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             // For use items, skip rewriting attributes. Just check for a skip attribute.
             ast::ItemKind::Use(..) => {
                 if contains_skip(attrs) {
-                    self.push_skipped_with_span(attrs.as_slice(), item.span());
+                    self.push_skipped_with_span(attrs.as_slice(), item.span(), item.span());
                     return;
                 }
             }
             // Module is inline, in this case we treat it like any other item.
             _ if !is_mod_decl(item) => {
                 if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) {
-                    self.push_skipped_with_span(item.attrs.as_slice(), item.span());
+                    self.push_skipped_with_span(item.attrs.as_slice(), item.span(), item.span());
                     return;
                 }
             }
@@ -357,7 +357,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             }
             _ => {
                 if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) {
-                    self.push_skipped_with_span(item.attrs.as_slice(), item.span());
+                    self.push_skipped_with_span(item.attrs.as_slice(), item.span(), item.span());
                     return;
                 }
             }
@@ -474,7 +474,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         skip_out_of_file_lines_range_visitor!(self, ti.span);
 
         if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) {
-            self.push_skipped_with_span(ti.attrs.as_slice(), ti.span());
+            self.push_skipped_with_span(ti.attrs.as_slice(), ti.span(), ti.span());
             return;
         }
 
@@ -518,7 +518,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         skip_out_of_file_lines_range_visitor!(self, ii.span);
 
         if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) {
-            self.push_skipped_with_span(ii.attrs.as_slice(), ii.span());
+            self.push_skipped_with_span(ii.attrs.as_slice(), ii.span(), ii.span());
             return;
         }
 
@@ -592,7 +592,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         self.push_rewrite_inner(span, rewrite);
     }
 
-    pub fn push_skipped_with_span(&mut self, attrs: &[ast::Attribute], item_span: Span) {
+    pub fn push_skipped_with_span(
+        &mut self,
+        attrs: &[ast::Attribute],
+        item_span: Span,
+        main_span: Span,
+    ) {
         self.format_missing_with_indent(source!(self, item_span).lo());
         // do not take into account the lines with attributes as part of the skipped range
         let attrs_end = attrs
@@ -600,8 +605,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             .map(|attr| self.source_map.lookup_char_pos(attr.span().hi()).line)
             .max()
             .unwrap_or(1);
-        // Add 1 to get the line past the last attribute
-        let lo = attrs_end + 1;
+        let first_line = self.source_map.lookup_char_pos(main_span.lo()).line;
+        // Statement can start after some newlines and/or spaces
+        // or it can be on the same line as the last attribute.
+        // So here we need to take a minimum between two.
+        let lo = std::cmp::min(attrs_end + 1, first_line);
         self.push_rewrite_inner(item_span, None);
         let hi = self.line_number + 1;
         self.skipped_range.push((lo, hi));