Merge pull request #1918 from topecongiro/issue-1917

Ignore empty lines inside arguments of macro with brace
This commit is contained in:
Nick Cameron 2017-08-28 09:06:54 +12:00 committed by GitHub
commit 565492083f
4 changed files with 123 additions and 21 deletions

View File

@ -231,6 +231,16 @@ pub fn new(block_indent: usize, alignment: usize) -> Indent {
}
}
pub fn from_width(config: &Config, width: usize) -> Indent {
if config.hard_tabs() {
let tab_num = width / config.tab_spaces();
let alignment = width % config.tab_spaces();
Indent::new(config.tab_spaces() * tab_num, alignment)
} else {
Indent::new(width, 0)
}
}
pub fn empty() -> Indent {
Indent::new(0, 0)
}

View File

@ -19,8 +19,6 @@
// List-like invocations with parentheses will be formatted as function calls,
// and those with brackets will be formatted as array literals.
use std::iter::repeat;
use syntax::ast;
use syntax::codemap::BytePos;
use syntax::parse::new_parser_from_tts;
@ -118,14 +116,18 @@ pub fn rewrite_macro(
Ok(expr) => {
// Recovered errors.
if context.parse_session.span_diagnostic.has_errors() {
return indent_macro_snippet(&context.snippet(mac.span), shape.indent);
return indent_macro_snippet(
context,
&context.snippet(mac.span),
shape.indent,
);
}
expr
}
Err(mut e) => {
e.cancel();
return indent_macro_snippet(&context.snippet(mac.span), shape.indent);
return indent_macro_snippet(context, &context.snippet(mac.span), shape.indent);
}
};
@ -244,7 +246,7 @@ pub fn rewrite_macro(
}
MacroStyle::Braces => {
// Skip macro invocations with braces, for now.
indent_macro_snippet(&context.snippet(mac.span), shape.indent)
indent_macro_snippet(context, &context.snippet(mac.span), shape.indent)
}
}
}
@ -308,32 +310,62 @@ fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle {
// ),
/// }
/// ```
fn indent_macro_snippet(macro_str: &str, indent: Indent) -> Option<String> {
let min_prefix_space_width =
try_opt!(macro_str.lines().skip(1).map(get_prefix_space_width).min());
fn indent_macro_snippet(
context: &RewriteContext,
macro_str: &str,
indent: Indent,
) -> Option<String> {
let mut lines = macro_str.lines();
let first_line = try_opt!(lines.next());
let first_line = try_opt!(lines.next().map(|s| s.trim_right()));
let mut trimmed_lines = Vec::with_capacity(16);
let min_prefix_space_width = try_opt!(
lines
.filter_map(|line| {
let prefix_space_width = if is_empty_line(line) {
None
} else {
Some(get_prefix_space_width(context, line))
};
trimmed_lines.push((line.trim(), prefix_space_width));
prefix_space_width
})
.min()
);
Some(
String::from(first_line) + "\n" +
&lines
.map(|line| {
let new_indent_width = indent.width() +
get_prefix_space_width(line)
.checked_sub(min_prefix_space_width)
.unwrap_or(0);
repeat_white_space(new_indent_width) + line.trim()
&trimmed_lines
.iter()
.map(|&(line, prefix_space_width)| match prefix_space_width {
Some(original_indent_width) => {
let new_indent_width = indent.width() +
original_indent_width
.checked_sub(min_prefix_space_width)
.unwrap_or(0);
let new_indent = Indent::from_width(context.config, new_indent_width);
new_indent.to_string(context.config) + line.trim()
}
None => String::new(),
})
.collect::<Vec<_>>()
.join("\n"),
)
}
fn get_prefix_space_width(s: &str) -> usize {
s.chars().position(|c| c != ' ').unwrap_or(0)
fn get_prefix_space_width(context: &RewriteContext, s: &str) -> usize {
let mut width = 0;
let mut iter = s.chars();
while let Some(c) = iter.next() {
match c {
' ' => width += 1,
'\t' => width += context.config.tab_spaces(),
_ => return width,
}
}
width
}
fn repeat_white_space(ws_count: usize) -> String {
repeat(" ").take(ws_count).collect::<String>()
fn is_empty_line(s: &str) -> bool {
s.is_empty() || s.chars().all(char::is_whitespace)
}

View File

@ -134,6 +134,36 @@ fn issue_1885() {
}).collect::<Vec<_>>();
}
fn issue_1917() {
mod x {
quickcheck! {
fn test(a: String, s: String, b: String) -> TestResult {
if a.find(&s).is_none() {
TestResult::from_bool(true)
} else {
TestResult::discard()
}
}
}
}
}
fn issue_1921() {
// Macro with tabs.
lazy_static! {
static ref ONE: u32 = 1;
static ref TWO: u32 = 2;
static ref THREE: u32 = 3;
static ref FOUR: u32 = {
let mut acc = 1;
acc += 1;
acc += 2;
acc
}
}
}
// Put the following tests with macro invocations whose arguments cannot be parsed as expressioins
// at the end of the file for now.

View File

@ -178,6 +178,36 @@ fn issue_1885() {
.collect::<Vec<_>>();
}
fn issue_1917() {
mod x {
quickcheck! {
fn test(a: String, s: String, b: String) -> TestResult {
if a.find(&s).is_none() {
TestResult::from_bool(true)
} else {
TestResult::discard()
}
}
}
}
}
fn issue_1921() {
// Macro with tabs.
lazy_static! {
static ref ONE: u32 = 1;
static ref TWO: u32 = 2;
static ref THREE: u32 = 3;
static ref FOUR: u32 = {
let mut acc = 1;
acc += 1;
acc += 2;
acc
}
}
}
// Put the following tests with macro invocations whose arguments cannot be parsed as expressioins
// at the end of the file for now.