about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSeiichi Uchida <seuchida@gmail.com>2017-08-15 00:28:31 +0900
committerGitHub <noreply@github.com>2017-08-15 00:28:31 +0900
commita1d28bf41cbec4748633bbe336145a862429b265 (patch)
tree868140274c71a9cc32ec16ec38f8026ee130f318
parent16920fb5c50a0ea8aee97fb381a8d92c2c215e38 (diff)
parentf9ee060eae6324a15f90e772b3db4d71f4141a6f (diff)
Merge pull request #1872 from sinkuu/remove_newline
Remove blank lines at start or end of block 
-rw-r--r--src/bin/cargo-fmt.rs1
-rw-r--r--src/bin/rustfmt.rs1
-rw-r--r--src/config.rs4
-rw-r--r--src/expr.rs1
-rw-r--r--src/filemap.rs1
-rw-r--r--src/types.rs2
-rw-r--r--src/visitor.rs73
-rw-r--r--tests/source/fn-simple.rs1
-rw-r--r--tests/source/indent_match_arms.rs1
-rw-r--r--tests/source/issue-510.rs1
-rw-r--r--tests/source/remove_blank_lines.rs22
-rw-r--r--tests/source/spaces-within-angle-brackets.rs1
-rw-r--r--tests/source/spaces-within-parens.rs1
-rw-r--r--tests/source/spaces-within-square-brackets.rs1
-rw-r--r--tests/source/struct_tuple_visual.rs2
-rw-r--r--tests/target/fn-simple.rs1
-rw-r--r--tests/target/indent_match_arms.rs1
-rw-r--r--tests/target/issue-510.rs1
-rw-r--r--tests/target/remove_blank_lines.rs11
-rw-r--r--tests/target/spaces-within-angle-brackets.rs1
-rw-r--r--tests/target/spaces-within-parens.rs1
-rw-r--r--tests/target/spaces-within-square-brackets.rs1
-rw-r--r--tests/target/struct_tuple_visual.rs2
23 files changed, 105 insertions, 27 deletions
diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs
index b07a40804dd..2c0ec3a84dc 100644
--- a/src/bin/cargo-fmt.rs
+++ b/src/bin/cargo-fmt.rs
@@ -271,7 +271,6 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result<Vec<Target>, std::
         std::io::ErrorKind::NotFound,
         str::from_utf8(&output.stderr).unwrap(),
     ))
-
 }
 
 fn target_from_json(jtarget: &Value) -> Target {
diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs
index d1f7a83187b..88bd3222fcb 100644
--- a/src/bin/rustfmt.rs
+++ b/src/bin/rustfmt.rs
@@ -102,7 +102,6 @@ fn match_cli_path_or_file(
     config_path: Option<PathBuf>,
     input_file: &Path,
 ) -> FmtResult<(Config, Option<PathBuf>)> {
-
     if let Some(config_file) = config_path {
         let toml = Config::from_toml_path(config_file.as_ref())?;
         return Ok((toml, Some(config_file)));
diff --git a/src/config.rs b/src/config.rs
index fbba5e19490..11d64dc073f 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -606,7 +606,9 @@ create_config! {
                                               tuple patterns";
     combine_control_expr: bool, true, "Combine control expressions with funciton calls.";
     struct_field_align_threshold: usize, 0, "Align struct fields if their diffs fits within \
-                                             threshold."
+                                             threshold.";
+    remove_blank_lines_at_start_or_end_of_block: bool, true,
+        "Remove blank lines at start or end of a block";
 }
 
 #[cfg(test)]
diff --git a/src/expr.rs b/src/expr.rs
index c785f4883c4..b9da6d83813 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -2937,7 +2937,6 @@ fn choose_rhs(
 }
 
 fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool {
-
     fn count_line_breaks(src: &str) -> usize {
         src.chars().filter(|&x| x == '\n').count()
     }
diff --git a/src/filemap.rs b/src/filemap.rs
index ee0a21b39b1..72724da1c11 100644
--- a/src/filemap.rs
+++ b/src/filemap.rs
@@ -90,7 +90,6 @@ pub fn write_file<T>(
 where
     T: Write,
 {
-
     fn source_and_formatted_text(
         text: &StringBuffer,
         filename: &str,
diff --git a/src/types.rs b/src/types.rs
index f7cb3c53656..61ef03b1687 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -404,7 +404,6 @@ where
     } else {
         Some(format!("{}{}", args, output))
     }
-
 }
 
 fn type_bound_colon(context: &RewriteContext) -> &'static str {
@@ -601,7 +600,6 @@ impl Rewrite for ast::TyParam {
             result.push_str(&join_bounds(context, shape, &strs));
         }
         if let Some(ref def) = self.default {
-
             let eq_str = match context.config.type_punctuation_density() {
                 TypeDensity::Compressed => "=",
                 TypeDensity::Wide => " = ",
diff --git a/src/visitor.rs b/src/visitor.rs
index 4ef89979c3f..6faaf8805b3 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -12,12 +12,13 @@ use std::cmp;
 
 use strings::string_buffer::StringBuffer;
 use syntax::{ast, ptr, visit};
-use syntax::codemap::{self, BytePos, CodeMap, Span};
+use syntax::attr::HasAttrs;
+use syntax::codemap::{self, BytePos, CodeMap, Pos, Span};
 use syntax::parse::ParseSess;
 
 use {Indent, Shape, Spanned};
 use codemap::{LineRangeUtils, SpanUtils};
-use comment::{contains_comment, FindUncommented};
+use comment::{contains_comment, CodeCharKind, CommentCodeSlices, FindUncommented};
 use comment::rewrite_comment;
 use config::{BraceStyle, Config};
 use expr::{format_expr, ExprType};
@@ -131,6 +132,48 @@ impl<'a> FmtVisitor<'a> {
         self.block_indent = self.block_indent.block_indent(self.config);
         self.buffer.push_str("{");
 
+        if self.config.remove_blank_lines_at_start_or_end_of_block() {
+            if let Some(first_stmt) = b.stmts.first() {
+                let attr_lo = inner_attrs
+                    .and_then(|attrs| {
+                        utils::inner_attributes(attrs)
+                            .first()
+                            .map(|attr| attr.span.lo)
+                    })
+                    .or_else(|| {
+                        // Attributes for an item in a statement position
+                        // do not belong to the statement. (rust-lang/rust#34459)
+                        if let ast::StmtKind::Item(ref item) = first_stmt.node {
+                            item.attrs.first()
+                        } else {
+                            first_stmt.attrs().first()
+                        }.and_then(|attr| {
+                            // Some stmts can have embedded attributes.
+                            // e.g. `match { #![attr] ... }`
+                            let attr_lo = attr.span.lo;
+                            if attr_lo < first_stmt.span.lo {
+                                Some(attr_lo)
+                            } else {
+                                None
+                            }
+                        })
+                    });
+
+                let snippet =
+                    self.snippet(mk_sp(self.last_pos, attr_lo.unwrap_or(first_stmt.span.lo)));
+                let len = CommentCodeSlices::new(&snippet).nth(0).and_then(
+                    |(kind, _, s)| if kind == CodeCharKind::Normal {
+                        s.rfind('\n')
+                    } else {
+                        None
+                    },
+                );
+                if let Some(len) = len {
+                    self.last_pos = self.last_pos + BytePos::from_usize(len);
+                }
+            }
+        }
+
         // Format inner attributes if available.
         if let Some(attrs) = inner_attrs {
             self.visit_attrs(attrs, ast::AttrStyle::Inner);
@@ -148,9 +191,31 @@ impl<'a> FmtVisitor<'a> {
             }
         }
 
+        let mut remove_len = BytePos(0);
+        if self.config.remove_blank_lines_at_start_or_end_of_block() {
+            if let Some(stmt) = b.stmts.last() {
+                let snippet = self.snippet(mk_sp(
+                    stmt.span.hi,
+                    source!(self, b.span).hi - brace_compensation,
+                ));
+                let len = CommentCodeSlices::new(&snippet)
+                    .last()
+                    .and_then(|(kind, _, s)| {
+                        if kind == CodeCharKind::Normal && s.trim().is_empty() {
+                            Some(s.len())
+                        } else {
+                            None
+                        }
+                    });
+                if let Some(len) = len {
+                    remove_len = BytePos::from_usize(len);
+                }
+            }
+        }
+
         let mut unindent_comment = self.is_if_else_block && !b.stmts.is_empty();
         if unindent_comment {
-            let end_pos = source!(self, b.span).hi - brace_compensation;
+            let end_pos = source!(self, b.span).hi - brace_compensation - remove_len;
             let snippet = self.get_context().snippet(mk_sp(self.last_pos, end_pos));
             unindent_comment = snippet.contains("//") || snippet.contains("/*");
         }
@@ -158,7 +223,7 @@ impl<'a> FmtVisitor<'a> {
         if unindent_comment {
             self.block_indent = self.block_indent.block_unindent(self.config);
         }
-        self.format_missing_with_indent(source!(self, b.span).hi - brace_compensation);
+        self.format_missing_with_indent(source!(self, b.span).hi - brace_compensation - remove_len);
         if unindent_comment {
             self.block_indent = self.block_indent.block_indent(self.config);
         }
diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs
index e11df34ad86..e3d489411ad 100644
--- a/tests/source/fn-simple.rs
+++ b/tests/source/fn-simple.rs
@@ -51,5 +51,4 @@ pub fn waltz(cwd: &Path) -> CliAssert {
             formatted_comment = rewrite_comment(comment, block_style, width, offset, formatting_fig);
         }
     }
-
 }
diff --git a/tests/source/indent_match_arms.rs b/tests/source/indent_match_arms.rs
index ecadbe705ff..75cee57f10d 100644
--- a/tests/source/indent_match_arms.rs
+++ b/tests/source/indent_match_arms.rs
@@ -23,5 +23,4 @@ fn main() {
         },
         _ => "something else",
     }
-
 }
diff --git a/tests/source/issue-510.rs b/tests/source/issue-510.rs
index 8f56be02e32..4c60859e6cf 100644
--- a/tests/source/issue-510.rs
+++ b/tests/source/issue-510.rs
@@ -3,7 +3,6 @@ fn solve_inline_size_constraints(&self,
 block: &mut BlockFlow,
 input: &ISizeConstraintInput)
 -> ISizeConstraintSolution {
-
 let (inline_start,inline_size,margin_inline_start,margin_inline_end) =
 match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) {
 (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
diff --git a/tests/source/remove_blank_lines.rs b/tests/source/remove_blank_lines.rs
new file mode 100644
index 00000000000..377843cbc8b
--- /dev/null
+++ b/tests/source/remove_blank_lines.rs
@@ -0,0 +1,22 @@
+fn main() {
+
+
+
+
+    let x = 1;
+
+
+
+
+}
+
+fn foo() {
+
+    #![attribute]
+
+    let x = 1;
+
+    // comment
+
+
+}
diff --git a/tests/source/spaces-within-angle-brackets.rs b/tests/source/spaces-within-angle-brackets.rs
index fc8dcda4293..73cab841e2e 100644
--- a/tests/source/spaces-within-angle-brackets.rs
+++ b/tests/source/spaces-within-angle-brackets.rs
@@ -31,7 +31,6 @@ fn foo<T, E>(a: T, b: E) {
 }
 
 fn foo<T: Send, E: Send>(a: T, b: E) {
-
     foo::<u32, str>(10, "bar");
 
     let opt: Option<u32>;
diff --git a/tests/source/spaces-within-parens.rs b/tests/source/spaces-within-parens.rs
index 63978eaf854..dba8d7cf013 100644
--- a/tests/source/spaces-within-parens.rs
+++ b/tests/source/spaces-within-parens.rs
@@ -14,7 +14,6 @@ struct TupleStruct2(u32, u32);
 fn fooEmpty() {}
 
 fn foo(e: E, _: u32) -> (u32, u32) {
-
     // Tuples
     let t1 = ();
     let t2 = (1,);
diff --git a/tests/source/spaces-within-square-brackets.rs b/tests/source/spaces-within-square-brackets.rs
index 6988ce5ed1c..d0466cacdd5 100644
--- a/tests/source/spaces-within-square-brackets.rs
+++ b/tests/source/spaces-within-square-brackets.rs
@@ -1,7 +1,6 @@
 // rustfmt-spaces_within_square_brackets: true
 
 fn main() {
-
     let arr: [i32; 5] = [1, 2, 3, 4, 5];
     let arr: [i32; 500] = [0; 500];
 
diff --git a/tests/source/struct_tuple_visual.rs b/tests/source/struct_tuple_visual.rs
index 8f935c1aa4d..d7d9e961bc4 100644
--- a/tests/source/struct_tuple_visual.rs
+++ b/tests/source/struct_tuple_visual.rs
@@ -3,7 +3,6 @@
 // rustfmt-error_on_line_overflow: false
 // rustfmt-struct_lit_style: Visual
 fn foo() {
-
     Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b());
 
     Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment
@@ -35,5 +34,4 @@ fn foo() {
             //              /|\   \
             //             o o o   o
             G)
-
 }
diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs
index e381b6e6231..a9640937f60 100644
--- a/tests/target/fn-simple.rs
+++ b/tests/target/fn-simple.rs
@@ -96,5 +96,4 @@ pub fn waltz(cwd: &Path) -> CliAssert {
                 rewrite_comment(comment, block_style, width, offset, formatting_fig);
         }
     }
-
 }
diff --git a/tests/target/indent_match_arms.rs b/tests/target/indent_match_arms.rs
index e0b34dbe03d..8d5e7ef7887 100644
--- a/tests/target/indent_match_arms.rs
+++ b/tests/target/indent_match_arms.rs
@@ -23,5 +23,4 @@ fn main() {
     },
     _ => "something else",
     }
-
 }
diff --git a/tests/target/issue-510.rs b/tests/target/issue-510.rs
index 54fe361bb4e..a166b68498f 100644
--- a/tests/target/issue-510.rs
+++ b/tests/target/issue-510.rs
@@ -4,7 +4,6 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
         block: &mut BlockFlow,
         input: &ISizeConstraintInput,
     ) -> ISizeConstraintSolution {
-
         let (inline_start, inline_size, margin_inline_start, margin_inline_end) = match (
             inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,
             inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,
diff --git a/tests/target/remove_blank_lines.rs b/tests/target/remove_blank_lines.rs
new file mode 100644
index 00000000000..00de4a829f2
--- /dev/null
+++ b/tests/target/remove_blank_lines.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let x = 1;
+}
+
+fn foo() {
+    #![attribute]
+
+    let x = 1;
+
+    // comment
+}
diff --git a/tests/target/spaces-within-angle-brackets.rs b/tests/target/spaces-within-angle-brackets.rs
index 3969327b8ec..89335b602a4 100644
--- a/tests/target/spaces-within-angle-brackets.rs
+++ b/tests/target/spaces-within-angle-brackets.rs
@@ -31,7 +31,6 @@ fn foo< T, E >(a: T, b: E) {
 }
 
 fn foo< T: Send, E: Send >(a: T, b: E) {
-
     foo::< u32, str >(10, "bar");
 
     let opt: Option< u32 >;
diff --git a/tests/target/spaces-within-parens.rs b/tests/target/spaces-within-parens.rs
index 2a0a566ddea..651386c618b 100644
--- a/tests/target/spaces-within-parens.rs
+++ b/tests/target/spaces-within-parens.rs
@@ -14,7 +14,6 @@ struct TupleStruct2( u32, u32 );
 fn fooEmpty() {}
 
 fn foo( e: E, _: u32 ) -> ( u32, u32 ) {
-
     // Tuples
     let t1 = ();
     let t2 = ( 1, );
diff --git a/tests/target/spaces-within-square-brackets.rs b/tests/target/spaces-within-square-brackets.rs
index 3a1b24d4def..cb468d6b59e 100644
--- a/tests/target/spaces-within-square-brackets.rs
+++ b/tests/target/spaces-within-square-brackets.rs
@@ -1,7 +1,6 @@
 // rustfmt-spaces_within_square_brackets: true
 
 fn main() {
-
     let arr: [ i32; 5 ] = [ 1, 2, 3, 4, 5 ];
     let arr: [ i32; 500 ] = [ 0; 500 ];
 
diff --git a/tests/target/struct_tuple_visual.rs b/tests/target/struct_tuple_visual.rs
index e63bc2c47c2..02811668bcb 100644
--- a/tests/target/struct_tuple_visual.rs
+++ b/tests/target/struct_tuple_visual.rs
@@ -3,7 +3,6 @@
 // rustfmt-error_on_line_overflow: false
 // rustfmt-struct_lit_style: Visual
 fn foo() {
-
     Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b());
 
     Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(
@@ -45,5 +44,4 @@ fn foo() {
         //             o o o   o
         G,
     )
-
 }