diff --git a/build.rs b/build.rs index 4f4a63be436..aca96774d06 100644 --- a/build.rs +++ b/build.rs @@ -16,11 +16,11 @@ fn main() { writeln!(f, "const COMMIT_HASH: Option<&'static str> = {:?};", git_head_sha1()) - .unwrap(); + .unwrap(); writeln!(f, "const WORKTREE_CLEAN: Option = {:?};", git_tree_is_clean()) - .unwrap(); + .unwrap(); // cargo:rerun-if-changed requires one entry per individual file. for entry in WalkDir::new("src") { diff --git a/src/chains.rs b/src/chains.rs index 209c0eb1382..fbc42a5d84e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -126,9 +126,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // brace. (parent_shape, false) } else if parent_rewrite_contains_newline { - (chain_indent(context, - parent_shape.block_indent(context.config.tab_spaces())), - false) + (chain_indent(context, parent_shape), false) } else { (shape.block_indent(context.config.tab_spaces()), false) }; @@ -142,17 +140,11 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ..nested_shape }; let first_child_shape = if extend { - let mut shape = try_opt!(parent_shape.offset_left(last_line_width(&parent_rewrite))); + let first_child_shape = try_opt!(parent_shape + .offset_left(last_line_width(&parent_rewrite))); match context.config.chain_indent() { - IndentStyle::Visual => shape, - IndentStyle::Block => { - shape.offset = shape - .offset - .checked_sub(context.config.tab_spaces()) - .unwrap_or(0); - shape.indent.block_indent += context.config.tab_spaces(); - shape - } + IndentStyle::Visual => first_child_shape, + IndentStyle::Block => first_child_shape.block(), } } else { other_child_shape @@ -181,7 +173,6 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if rewrites.len() > 1 { true } else if rewrites.len() == 1 { - let one_line_len = parent_rewrite.len() + first_line_width(&rewrites[0]); one_line_len > shape.width } else { false diff --git a/src/expr.rs b/src/expr.rs index 066c7faa43e..9c4f48bbb7e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -120,7 +120,7 @@ fn format_expr(expr: &ast::Expr, expr_type == ExprType::SubExpression, false, expr.span) - .rewrite(context, shape) + .rewrite(context, shape) } ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { ControlFlow::new_if(cond, @@ -130,7 +130,7 @@ fn format_expr(expr: &ast::Expr, expr_type == ExprType::SubExpression, false, expr.span) - .rewrite(context, shape) + .rewrite(context, shape) } ast::ExprKind::Match(ref cond, ref arms) => { rewrite_match(context, cond, arms, shape, expr.span) @@ -286,7 +286,7 @@ pub fn rewrite_pair(lhs: &LHS, let remaining_width = shape .width - .checked_sub(last_line_width(&result)) + .checked_sub(last_line_width(&result) + suffix.len()) .unwrap_or(0); if rhs_result.len() <= remaining_width { @@ -372,7 +372,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, |item| item.rewrite(context, nested_shape), span.lo, span.hi) - .collect::>(); + .collect::>(); if items.is_empty() { if context.config.spaces_within_square_brackets() { @@ -716,7 +716,7 @@ impl Rewrite for ast::Stmt { }, context, try_opt!(shape.sub_width(suffix.len()))) - .map(|s| s + suffix) + .map(|s| s + suffix) } ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, @@ -1012,7 +1012,7 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape) + .rewrite(context, shape) } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if(cond, @@ -1022,7 +1022,7 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape) + .rewrite(context, shape) } _ => { last_in_chain = true; @@ -1065,7 +1065,7 @@ impl<'a> Rewrite for ControlFlow<'a> { .as_ref() .map_or(between_sep, |s| &**s), after_else_comment.as_ref().map_or(after_sep, |s| &**s)) - .ok()); + .ok()); result.push_str(&try_opt!(rewrite)); } @@ -2080,11 +2080,18 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, 0 }; // 1 = space between operator and rhs. - let max_width = try_opt!(shape.width.checked_sub(last_line_width + 1)); - let rhs = ex.rewrite(context, - Shape::offset(max_width, - shape.indent, - shape.indent.alignment + last_line_width + 1)); + let orig_shape = try_opt!(shape.block_indent(0).offset_left(last_line_width + 1)); + let rhs = match ex.node { + ast::ExprKind::Mac(ref mac) => { + match rewrite_macro(mac, None, context, orig_shape, MacroPosition::Expression) { + None if !context.snippet(ex.span).contains("\n") => { + context.snippet(ex.span).rewrite(context, orig_shape) + } + rhs @ _ => rhs, + } + } + _ => ex.rewrite(context, orig_shape), + }; fn count_line_breaks(src: &str) -> usize { src.chars().filter(|&x| x == '\n').count() @@ -2099,10 +2106,7 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, // Expression did not fit on the same line as the identifier or is // at least three lines big. Try splitting the line and see // if that works better. - let new_offset = shape.indent.block_indent(context.config); - let max_width = try_opt!((shape.width + shape.indent.width()) - .checked_sub(new_offset.width())); - let new_shape = Shape::legacy(max_width, new_offset); + let new_shape = try_opt!(shape.block_left(context.config.tab_spaces())); let new_rhs = ex.rewrite(context, new_shape); // FIXME: DRY! @@ -2111,11 +2115,11 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 || (orig_rhs.rewrite(context, shape).is_none() && replacement_rhs.rewrite(context, new_shape).is_some()) => { - result.push_str(&format!("\n{}", new_offset.to_string(context.config))); + result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config))); result.push_str(replacement_rhs); } (None, Some(ref final_rhs)) => { - result.push_str(&format!("\n{}", new_offset.to_string(context.config))); + result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config))); result.push_str(final_rhs); } (None, None) => return None, diff --git a/src/items.rs b/src/items.rs index 953aecb3305..f98cf9507e1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -332,7 +332,7 @@ impl<'a> FmtVisitor<'a> { let suffix = if semicolon_for_expr(e) { ";" } else { "" }; e.rewrite(&self.get_context(), - Shape::indented(self.block_indent, self.config)) + Shape::indented(self.block_indent, self.config)) .map(|s| s + suffix) .or_else(|| Some(self.snippet(e.span))) } @@ -376,7 +376,7 @@ impl<'a> FmtVisitor<'a> { enum_def.variants.is_empty(), self.block_indent, mk_sp(span.lo, body_start)) - .unwrap(); + .unwrap(); self.buffer.push_str(&generics_str); self.last_pos = body_start; @@ -941,7 +941,7 @@ fn format_struct_struct(context: &RewriteContext, |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), context.codemap.span_after(span, "{"), span.hi) - .collect::>(); + .collect::>(); // 1 = , let budget = context.config.max_width() - offset.width() + context.config.tab_spaces() - 1; @@ -1295,7 +1295,7 @@ pub fn rewrite_static(prefix: &str, lhs, expr, Shape::legacy(remaining_width, offset.block_only())) - .map(|s| s + ";") + .map(|s| s + ";") } else { let lhs = format!("{}{};", prefix, ty_str); Some(lhs) diff --git a/src/lists.rs b/src/lists.rs index a48f9a382e6..3448f8a446a 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -266,7 +266,8 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option // Post-comments if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); - let formatted_comment = try_opt!(rewrite_comment(comment, + let formatted_comment = + try_opt!(rewrite_comment(comment, true, Shape::legacy(formatting.shape.width, Indent::empty()), formatting.config)); diff --git a/src/macros.rs b/src/macros.rs index b5644fb014c..a5ead34c9ec 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,7 +29,7 @@ use syntax::util::ThinVec; use Shape; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; -use expr::{rewrite_call, rewrite_array}; +use expr::{rewrite_call, rewrite_array, rewrite_pair}; use comment::{FindUncommented, contains_comment}; const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; @@ -105,6 +105,7 @@ pub fn rewrite_macro(mac: &ast::Mac, let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone()); let mut expr_vec = Vec::new(); + let mut vec_with_semi = false; if MacroStyle::Braces != style { loop { @@ -128,6 +129,29 @@ pub fn rewrite_macro(mac: &ast::Mac, match parser.token { Token::Eof => break, Token::Comma => (), + Token::Semi => { + // Try to parse `vec![expr; expr]` + if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { + parser.bump(); + if parser.token != Token::Eof { + match parser.parse_expr() { + Ok(expr) => { + if context.parse_session.span_diagnostic.has_errors() { + return None; + } + expr_vec.push(expr); + parser.bump(); + if parser.token == Token::Eof && expr_vec.len() == 2 { + vec_with_semi = true; + break; + } + } + Err(mut e) => e.cancel(), + } + } + } + return None; + } _ => return None, } @@ -156,18 +180,35 @@ pub fn rewrite_macro(mac: &ast::Mac, }) } MacroStyle::Brackets => { - // Format macro invocation as array literal. - let extra_offset = macro_name.len(); - let shape = try_opt!(shape.shrink_left(extra_offset)); - let rewrite = - try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), - mk_sp(context.codemap.span_after(mac.span, - original_style.opener()), - mac.span.hi - BytePos(1)), - context, - shape)); + let mac_shape = try_opt!(shape.shrink_left(macro_name.len())); + // Handle special case: `vec![expr; expr]` + if vec_with_semi { + let (lbr, rbr) = if context.config.spaces_within_square_brackets() { + ("[ ", " ]") + } else { + ("[", "]") + }; + rewrite_pair(&*expr_vec[0], + &*expr_vec[1], + lbr, + "; ", + rbr, + context, + mac_shape) + .map(|s| format!("{}{}", macro_name, s)) + } else { + // Format macro invocation as array literal. + let rewrite = + try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), + mk_sp(context.codemap.span_after(mac.span, + original_style + .opener()), + mac.span.hi - BytePos(1)), + context, + mac_shape)); - Some(format!("{}{}", macro_name, rewrite)) + Some(format!("{}{}", macro_name, rewrite)) + } } MacroStyle::Braces => { // Skip macro invocations with braces, for now. diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 2f4dda2a1b4..d6157cd6a29 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -163,7 +163,7 @@ impl<'a> FmtVisitor<'a> { Shape::legacy(comment_width, self.block_indent), self.config) - .unwrap()); + .unwrap()); last_wspace = None; line_start = offset + subslice.len(); diff --git a/src/patterns.rs b/src/patterns.rs index 5dc70f6d2d8..afea0ddb299 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -293,7 +293,7 @@ fn rewrite_tuple_pat(pats: &[ptr::P], |item| item.rewrite(context, nested_shape), context.codemap.span_after(span, "("), span.hi - BytePos(1)) - .collect(); + .collect(); // Condense wildcard string suffix into a single .. let wildcard_suffix_len = count_wildcard_suffix_len(&items); diff --git a/src/types.rs b/src/types.rs index ffa9639005a..570755d4441 100644 --- a/src/types.rs +++ b/src/types.rs @@ -364,7 +364,9 @@ impl Rewrite for ast::WherePredicate { let colon = type_bound_colon(context); if !bound_lifetimes.is_empty() { - let lifetime_str: String = try_opt!(bound_lifetimes.iter() + let lifetime_str: String = + try_opt!(bound_lifetimes + .iter() .map(|lt| lt.rewrite(context, shape)) .intersperse(Some(", ".to_string())) .collect()); @@ -376,14 +378,17 @@ impl Rewrite for ast::WherePredicate { // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; let budget = try_opt!(shape.width.checked_sub(used_width)); - let bounds_str: String = try_opt!(bounds.iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - Shape::legacy(budget, - shape.indent + used_width)) - }) - .intersperse(Some(joiner.to_string())) - .collect()); + let bounds_str: String = + try_opt!(bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, + Shape::legacy(budget, + shape.indent + + used_width)) + }) + .intersperse(Some(joiner.to_string())) + .collect()); if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { format!("for< {} > {}{}{}", @@ -401,14 +406,17 @@ impl Rewrite for ast::WherePredicate { }; let used_width = type_str.len() + colon.len(); let budget = try_opt!(shape.width.checked_sub(used_width)); - let bounds_str: String = try_opt!(bounds.iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - Shape::legacy(budget, - shape.indent + used_width)) - }) - .intersperse(Some(joiner.to_string())) - .collect()); + let bounds_str: String = + try_opt!(bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, + Shape::legacy(budget, + shape.indent + + used_width)) + }) + .intersperse(Some(joiner.to_string())) + .collect()); format!("{}{}{}", type_str, colon, bounds_str) } diff --git a/src/visitor.rs b/src/visitor.rs index 0e6817be4f7..96327ef96a7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -282,10 +282,10 @@ impl<'a> FmtVisitor<'a> { item.span, indent, None) - .map(|s| match *def { - ast::VariantData::Tuple(..) => s + ";", - _ => s, - }) + .map(|s| match *def { + ast::VariantData::Tuple(..) => s + ";", + _ => s, + }) }; self.push_rewrite(item.span, rewrite); } diff --git a/tests/source/configs-fn_call_style-block.rs b/tests/source/configs-fn_call_style-block.rs index 4013b2d9b25..35030189b8b 100644 --- a/tests/source/configs-fn_call_style-block.rs +++ b/tests/source/configs-fn_call_style-block.rs @@ -15,3 +15,33 @@ impl Foo { } } } + +fn issue1420() { + given( + r#" + # Getting started + ... + "#, + ) + .running(waltz) +} + +// #1563 +fn query(conn: &Connection) -> Result<()> { + conn.query_row( + r#" + SELECT title, date + FROM posts, + WHERE DATE(date) = $1 + "#, + &[], + |row| { + Post { + title: row.get(0), + date: row.get(1), + } + }, + )?; + + Ok(()) +} diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 3eee8c543ba..b83f74c47d5 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -34,6 +34,19 @@ fn main() { a, ]; + vec![a; b]; + vec!(a; b); + vec!{a; b}; + + vec![a, b; c]; + vec![a; b, c]; + + vec![a; (|x| { let y = x + 1; let z = y + 1; z })(2)]; + vec![a; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; + vec![a; unsafe { + x + 1 + }]; + unknown_bracket_macro__comma_should_not_be_stripped![ a, ]; diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index c9a42cd4952..d7f65635379 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -28,3 +28,33 @@ impl Foo { } } } + +fn issue1420() { + given( + r#" + # Getting started + ... + "# + ) + .running(waltz) +} + +// #1563 +fn query(conn: &Connection) -> Result<()> { + conn.query_row( + r#" + SELECT title, date + FROM posts, + WHERE DATE(date) = $1 + "#, + &[], + |row| { + Post { + title: row.get(0), + date: row.get(1), + } + }, + )?; + + Ok(()) +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 1fd8130f824..c19bb242ca3 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -38,6 +38,23 @@ fn main() { // Trailing spaces after a comma vec![a]; + vec![a; b]; + vec![a; b]; + vec![a; b]; + + vec![a, b; c]; + vec![a; b, c]; + + vec![a; + (|x| { + let y = x + 1; + let z = y + 1; + z + })(2)]; + vec![a; + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; + vec![a; unsafe { x + 1 }]; + unknown_bracket_macro__comma_should_not_be_stripped![ a, ]; diff --git a/tests/target/match.rs b/tests/target/match.rs index 15b7889e476..09df7ebd55f 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -158,19 +158,19 @@ fn issue355() { match mac { a => println!("a", b), b => vec![1, 2], - c => vec!(3; 4), + c => vec![3; 4], d => println!("a", b), e => vec![1, 2], - f => vec!(3; 4), + f => vec![3; 4], h => println!("a", b), // h comment i => vec![1, 2], // i comment - j => vec!(3; 4), // j comment + j => vec![3; 4], // j comment // k comment k => println!("a", b), // l comment l => vec![1, 2], // m comment - m => vec!(3; 4), + m => vec![3; 4], // Rewrite splits macro nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { println!("a", b) @@ -182,7 +182,7 @@ fn issue355() { // Macro support fails to recognise this macro as splitable // We push the whole expr to a new line, TODO split this macro as well pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => { - vec!(3; 4) + vec![3; 4] } // q, r and s: Rewrite splits match arm qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => { @@ -192,19 +192,19 @@ fn issue355() { vec![1, 2] } ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => { - vec!(3; 4) + vec![3; 4] } // Funky bracketing styles t => println!{"a", b}, u => vec![1, 2], - v => vec!{3; 4}, + v => vec![3; 4], w => println!["a", b], x => vec![1, 2], y => vec![3; 4], // Brackets with comments tc => println!{"a", b}, // comment uc => vec![1, 2], // comment - vc => vec!{3; 4}, // comment + vc => vec![3; 4], // comment wc => println!["a", b], // comment xc => vec![1, 2], // comment yc => vec![3; 4], // comment