From b433e63d2a952db18fd079cbf8ec1cf49b0d076b Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 11 Aug 2017 16:15:28 +0900 Subject: [PATCH 1/4] Remove unnecessary blank lines at the start and the end of a block --- src/config.rs | 4 ++- src/visitor.rs | 49 ++++++++++++++++++++++++++++-- tests/source/remove_blank_lines.rs | 22 ++++++++++++++ tests/target/remove_blank_lines.rs | 11 +++++++ 4 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 tests/source/remove_blank_lines.rs create mode 100644 tests/target/remove_blank_lines.rs diff --git a/src/config.rs b/src/config.rs index fbba5e19490f..11d64dc073fb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -606,7 +606,9 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { 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/visitor.rs b/src/visitor.rs index 4ef89979c3ff..b455e569e435 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -17,7 +17,7 @@ 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 +131,27 @@ pub fn visit_block(&mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribu 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(stmt) = b.stmts.first() { + let snippet = self.snippet(mk_sp(self.last_pos, stmt.span.lo)); + let len = CommentCodeSlices::new(&snippet) + .nth(0) + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal { + // There may be inner attributes + let s = &s[..s.len() - + s.trim_left_matches(&[' ', '\t', '\r', '\n'][..]).len()]; + s.rfind('\n') + } else { + None + } + }); + if let Some(len) = len { + self.last_pos = self.last_pos + BytePos(len as u32); + } + } + } + // Format inner attributes if available. if let Some(attrs) = inner_attrs { self.visit_attrs(attrs, ast::AttrStyle::Inner); @@ -148,9 +169,31 @@ pub fn visit_block(&mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribu } } + 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(len as u32); + } + } + } + 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 +201,7 @@ pub fn visit_block(&mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribu 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/remove_blank_lines.rs b/tests/source/remove_blank_lines.rs new file mode 100644 index 000000000000..377843cbc8b4 --- /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/target/remove_blank_lines.rs b/tests/target/remove_blank_lines.rs new file mode 100644 index 000000000000..00de4a829f2f --- /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 +} From fea3080f915cbf75b100bbba1f0b99d2839ca5e0 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 11 Aug 2017 16:17:12 +0900 Subject: [PATCH 2/4] Format --- src/bin/cargo-fmt.rs | 1 - src/bin/rustfmt.rs | 1 - src/expr.rs | 1 - src/filemap.rs | 1 - src/types.rs | 2 -- tests/source/fn-simple.rs | 1 - tests/source/indent_match_arms.rs | 1 - tests/source/issue-510.rs | 1 - tests/source/spaces-within-angle-brackets.rs | 1 - tests/source/spaces-within-parens.rs | 1 - tests/source/spaces-within-square-brackets.rs | 1 - tests/source/struct_tuple_visual.rs | 2 -- tests/target/fn-simple.rs | 1 - tests/target/indent_match_arms.rs | 1 - tests/target/issue-510.rs | 1 - tests/target/spaces-within-angle-brackets.rs | 1 - tests/target/spaces-within-parens.rs | 1 - tests/target/spaces-within-square-brackets.rs | 1 - tests/target/struct_tuple_visual.rs | 2 -- 19 files changed, 22 deletions(-) diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index b07a40804ddc..2c0ec3a84dcb 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -271,7 +271,6 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, 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 d1f7a83187b3..88bd3222fcb8 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -102,7 +102,6 @@ fn match_cli_path_or_file( config_path: Option, input_file: &Path, ) -> FmtResult<(Config, Option)> { - 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/expr.rs b/src/expr.rs index d0e5df3abbba..298b8143b531 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2985,7 +2985,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 ee0a21b39b13..72724da1c118 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -90,7 +90,6 @@ pub fn write_file( where T: Write, { - fn source_and_formatted_text( text: &StringBuffer, filename: &str, diff --git a/src/types.rs b/src/types.rs index f7cb3c536568..61ef03b16874 100644 --- a/src/types.rs +++ b/src/types.rs @@ -404,7 +404,6 @@ enum ArgumentKind } else { Some(format!("{}{}", args, output)) } - } fn type_bound_colon(context: &RewriteContext) -> &'static str { @@ -601,7 +600,6 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { 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/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index e11df34ad86d..e3d489411ad2 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 ecadbe705ffe..75cee57f10db 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 8f56be02e32d..4c60859e6cf3 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/spaces-within-angle-brackets.rs b/tests/source/spaces-within-angle-brackets.rs index fc8dcda42937..73cab841e2e6 100644 --- a/tests/source/spaces-within-angle-brackets.rs +++ b/tests/source/spaces-within-angle-brackets.rs @@ -31,7 +31,6 @@ fn foo(a: T, b: E) { } fn foo(a: T, b: E) { - foo::(10, "bar"); let opt: Option; diff --git a/tests/source/spaces-within-parens.rs b/tests/source/spaces-within-parens.rs index 63978eaf8543..dba8d7cf0130 100644 --- a/tests/source/spaces-within-parens.rs +++ b/tests/source/spaces-within-parens.rs @@ -14,7 +14,6 @@ enum E { 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 6988ce5ed1cd..d0466cacdd54 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 8f935c1aa4dc..d7d9e961bc44 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 e381b6e62314..a9640937f606 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 e0b34dbe03d9..8d5e7ef78874 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 54fe361bb4e7..a166b68498fa 100644 --- a/tests/target/issue-510.rs +++ b/tests/target/issue-510.rs @@ -4,7 +4,6 @@ fn solve_inline_size_constraints( 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/spaces-within-angle-brackets.rs b/tests/target/spaces-within-angle-brackets.rs index 3969327b8ec0..89335b602a42 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 2a0a566ddea8..651386c618bf 100644 --- a/tests/target/spaces-within-parens.rs +++ b/tests/target/spaces-within-parens.rs @@ -14,7 +14,6 @@ enum E { 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 3a1b24d4defc..cb468d6b59e6 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 e63bc2c47c2b..02811668bcba 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, ) - } From 955b25625d2f925261661a8fd7abfc322186886b Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 11 Aug 2017 22:16:24 +0900 Subject: [PATCH 3/4] Use attribute span --- src/visitor.rs | 54 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/visitor.rs b/src/visitor.rs index b455e569e435..8c911465722b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -12,7 +12,8 @@ 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}; @@ -132,22 +133,45 @@ pub fn visit_block(&mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribu self.buffer.push_str("{"); if self.config.remove_blank_lines_at_start_or_end_of_block() { - if let Some(stmt) = b.stmts.first() { - let snippet = self.snippet(mk_sp(self.last_pos, stmt.span.lo)); - let len = CommentCodeSlices::new(&snippet) - .nth(0) - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal { - // There may be inner attributes - let s = &s[..s.len() - - s.trim_left_matches(&[' ', '\t', '\r', '\n'][..]).len()]; - s.rfind('\n') + if let Some(first_stmt) = b.stmts.first() { + let attr_lo = inner_attrs + .and_then(|attrs| { + attrs + .iter() + .filter(|a| a.style == ast::AttrStyle::Inner) + .nth(0) + .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 { - None - } + 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(len as u32); + self.last_pos = self.last_pos + BytePos::from_usize(len); } } } @@ -186,7 +210,7 @@ pub fn visit_block(&mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribu } }); if let Some(len) = len { - remove_len = BytePos(len as u32); + remove_len = BytePos::from_usize(len); } } } From f9ee060eae6324a15f90e772b3db4d71f4141a6f Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sat, 12 Aug 2017 17:01:46 +0900 Subject: [PATCH 4/4] Use utils::inner_attributes --- src/visitor.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/visitor.rs b/src/visitor.rs index 8c911465722b..6faaf8805b3d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -136,10 +136,8 @@ pub fn visit_block(&mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribu if let Some(first_stmt) = b.stmts.first() { let attr_lo = inner_attrs .and_then(|attrs| { - attrs - .iter() - .filter(|a| a.style == ast::AttrStyle::Inner) - .nth(0) + utils::inner_attributes(attrs) + .first() .map(|attr| attr.span.lo) }) .or_else(|| {