1
Fork 0

Refine chain breaking heuristics

Don't make a single line chain when it is was multi line in the source; allow overflow of the last chain element onto the next lines without breaking the chain.
This commit is contained in:
Marcus Klaas 2015-09-09 23:17:31 +02:00
parent 48d17f54d3
commit 03c660633f
18 changed files with 351 additions and 202 deletions

View file

@ -20,7 +20,7 @@
// argument function argument strategy. // argument function argument strategy.
use rewrite::{Rewrite, RewriteContext}; use rewrite::{Rewrite, RewriteContext};
use utils::make_indent; use utils::{first_line_width, make_indent};
use expr::rewrite_call; use expr::rewrite_call;
use syntax::{ast, ptr}; use syntax::{ast, ptr};
@ -51,19 +51,67 @@ pub fn rewrite_chain(mut expr: &ast::Expr,
let indent = offset + extra_indent; let indent = offset + extra_indent;
let max_width = try_opt!(width.checked_sub(extra_indent)); let max_width = try_opt!(width.checked_sub(extra_indent));
let rewrites = try_opt!(subexpr_list.into_iter() let mut rewrites = try_opt!(subexpr_list.iter()
.rev() .rev()
.map(|e| { .map(|e| {
rewrite_chain_expr(e, rewrite_chain_expr(e,
total_span, total_span,
context, context,
max_width, max_width,
indent) indent)
}) })
.collect::<Option<Vec<_>>>()); .collect::<Option<Vec<_>>>());
let total_width = rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len(); // Total of all items excluding the last.
let fits_single_line = total_width <= width && rewrites.iter().all(|s| !s.contains('\n')); let almost_total = rewrites.split_last()
.unwrap()
.1
.iter()
.fold(0, |a, b| a + first_line_width(b)) +
parent_rewrite.len();
let total_width = almost_total + first_line_width(rewrites.last().unwrap());
let veto_single_line = if context.config.take_source_hints && subexpr_list.len() > 1 {
// Look at the source code. Unless all chain elements start on the same
// line, we won't consider putting them on a single line either.
let first_line_no = context.codemap.lookup_char_pos(subexpr_list[0].span.lo).line;
subexpr_list[1..]
.iter()
.any(|ex| context.codemap.lookup_char_pos(ex.span.hi).line != first_line_no)
} else {
false
};
let fits_single_line = !veto_single_line &&
match subexpr_list[0].node {
ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions)
if context.config.chains_overflow_last => {
let (last, init) = rewrites.split_last_mut().unwrap();
if init.iter().all(|s| !s.contains('\n')) && total_width <= width {
let last_rewrite = width.checked_sub(almost_total)
.and_then(|inner_width| {
rewrite_method_call(method_name.node,
types,
expressions,
total_span,
context,
inner_width,
offset + almost_total)
});
match last_rewrite {
Some(mut string) => {
::std::mem::swap(&mut string, last);
true
}
None => false,
}
} else {
false
}
}
_ => total_width <= width && rewrites.iter().all(|s| !s.contains('\n')),
};
let connector = if fits_single_line { let connector = if fits_single_line {
String::new() String::new()
@ -101,7 +149,11 @@ fn rewrite_chain_expr(expr: &ast::Expr,
-> Option<String> { -> Option<String> {
match expr.node { match expr.node {
ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => {
rewrite_method_call(method_name.node, types, expressions, span, context, width, offset) let inner = &RewriteContext {
block_indent: offset,
..*context
};
rewrite_method_call(method_name.node, types, expressions, span, inner, width, offset)
} }
ast::Expr_::ExprField(_, ref field) => { ast::Expr_::ExprField(_, ref field) => {
Some(format!(".{}", field.node)) Some(format!(".{}", field.node))
@ -137,10 +189,7 @@ fn rewrite_method_call(method_name: ast::Ident,
}; };
let callee_str = format!(".{}{}", method_name, type_str); let callee_str = format!(".{}{}", method_name, type_str);
let inner_context = &RewriteContext { let span = mk_sp(args[0].span.hi, span.hi);
block_indent: offset,
..*context
};
rewrite_call(inner_context, &callee_str, args, span, width, offset) rewrite_call(context, &callee_str, &args[1..], span, width, offset)
} }

View file

@ -133,8 +133,8 @@ create_config! {
fn_args_density: Density, fn_args_density: Density,
fn_args_layout: StructLitStyle, fn_args_layout: StructLitStyle,
fn_arg_indent: BlockIndentStyle, fn_arg_indent: BlockIndentStyle,
where_density: Density, // Should we at least try to put the where clause on the same line as where_density: Density, // Should we at least try to put the where clause on
// the rest of the function decl? // the same line as the rest of the function decl?
where_indent: BlockIndentStyle, // Visual will be treated like Tabbed where_indent: BlockIndentStyle, // Visual will be treated like Tabbed
where_layout: ListTactic, where_layout: ListTactic,
where_pred_indent: BlockIndentStyle, where_pred_indent: BlockIndentStyle,
@ -147,14 +147,14 @@ create_config! {
report_todo: ReportTactic, report_todo: ReportTactic,
report_fixme: ReportTactic, report_fixme: ReportTactic,
reorder_imports: bool, // Alphabetically, case sensitive. reorder_imports: bool, // Alphabetically, case sensitive.
expr_indent_style: BlockIndentStyle,
closure_indent_style: BlockIndentStyle,
single_line_if_else: bool, single_line_if_else: bool,
format_strings: bool, format_strings: bool,
chains_overflow_last: bool,
take_source_hints: bool, // Retain some formatting characteristics from
// the source code.
} }
impl Default for Config { impl Default for Config {
fn default() -> Config { fn default() -> Config {
Config { Config {
max_width: 100, max_width: 100,
@ -181,11 +181,10 @@ impl Default for Config {
report_todo: ReportTactic::Always, report_todo: ReportTactic::Always,
report_fixme: ReportTactic::Never, report_fixme: ReportTactic::Never,
reorder_imports: false, reorder_imports: false,
expr_indent_style: BlockIndentStyle::Tabbed,
closure_indent_style: BlockIndentStyle::Visual,
single_line_if_else: false, single_line_if_else: false,
format_strings: true, format_strings: true,
chains_overflow_last: true,
take_source_hints: true,
} }
} }
} }

View file

@ -40,6 +40,12 @@ impl Rewrite for ast::Expr {
} }
} }
ast::Expr_::ExprCall(ref callee, ref args) => { ast::Expr_::ExprCall(ref callee, ref args) => {
// FIXME using byte lens instead of char lens (and probably all over the place too)
// 2 is for parens
let max_callee_width = try_opt!(width.checked_sub(2));
let callee_str = try_opt!(callee.rewrite(context, max_callee_width, offset));
let span = mk_sp(callee.span.hi, self.span.hi);
rewrite_call(context, &**callee, args, self.span, width, offset) rewrite_call(context, &**callee, args, self.span, width, offset)
} }
ast::Expr_::ExprParen(ref subexpr) => { ast::Expr_::ExprParen(ref subexpr) => {
@ -284,8 +290,10 @@ impl Rewrite for ast::Block {
}; };
if is_simple_block(self, context.codemap) && prefix.len() < width { if is_simple_block(self, context.codemap) && prefix.len() < width {
let body = let body = self.expr
self.expr.as_ref().unwrap().rewrite(context, width - prefix.len(), offset); .as_ref()
.unwrap()
.rewrite(context, width - prefix.len(), offset);
if let Some(ref expr_str) = body { if let Some(ref expr_str) = body {
let result = format!("{}{{ {} }}", prefix, expr_str); let result = format!("{}{{ {} }}", prefix, expr_str);
if result.len() <= width && !result.contains('\n') { if result.len() <= width && !result.contains('\n') {
@ -677,15 +685,13 @@ impl Rewrite for ast::Arm {
total_width += (pat_strs.len() - 1) * 3; total_width += (pat_strs.len() - 1) * 3;
let mut vertical = total_width > pat_budget || pat_strs.iter().any(|p| p.contains('\n')); let mut vertical = total_width > pat_budget || pat_strs.iter().any(|p| p.contains('\n'));
if !vertical { if !vertical && context.config.take_source_hints {
// If the patterns were previously stacked, keep them stacked. // If the patterns were previously stacked, keep them stacked.
// FIXME should be an option.
let pat_span = mk_sp(pats[0].span.lo, pats[pats.len() - 1].span.hi); let pat_span = mk_sp(pats[0].span.lo, pats[pats.len() - 1].span.hi);
let pat_str = context.snippet(pat_span); let pat_str = context.snippet(pat_span);
vertical = pat_str.find('\n').is_some(); vertical = pat_str.find('\n').is_some();
} }
let pats_width = if vertical { let pats_width = if vertical {
pat_strs[pat_strs.len() - 1].len() pat_strs[pat_strs.len() - 1].len()
} else { } else {
@ -1015,9 +1021,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext,
match *item { match *item {
StructLitField::Regular(ref field) => field.span.lo, StructLitField::Regular(ref field) => field.span.lo,
StructLitField::Base(ref expr) => { StructLitField::Base(ref expr) => {
let last_field_hi = fields.last() let last_field_hi = fields.last().map_or(span.lo,
.map_or(span.lo, |field| {
|field| field.span.hi); field.span.hi
});
let snippet = context.snippet(mk_sp(last_field_hi, let snippet = context.snippet(mk_sp(last_field_hi,
expr.span.lo)); expr.span.lo));
let pos = snippet.find_uncommented("..").unwrap(); let pos = snippet.find_uncommented("..").unwrap();

View file

@ -512,8 +512,9 @@ impl<'a> FmtVisitor<'a> {
|arg| arg.ty.span.hi, |arg| arg.ty.span.hi,
|arg| { |arg| {
// FIXME silly width, indent // FIXME silly width, indent
arg.ty.rewrite(&self.get_context(), 1000, 0) arg.ty
.unwrap() .rewrite(&self.get_context(), 1000, 0)
.unwrap()
}, },
span_after(field.span, "(", self.codemap), span_after(field.span, "(", self.codemap),
next_span_start); next_span_start);
@ -810,15 +811,14 @@ impl<'a> FmtVisitor<'a> {
.map(|ty_param| ty_param.rewrite(&context, h_budget, offset).unwrap()); .map(|ty_param| ty_param.rewrite(&context, h_budget, offset).unwrap());
// Extract comments between generics. // Extract comments between generics.
let lt_spans = lifetimes.iter() let lt_spans = lifetimes.iter().map(|l| {
.map(|l| { let hi = if l.bounds.is_empty() {
let hi = if l.bounds.is_empty() { l.lifetime.span.hi
l.lifetime.span.hi } else {
} else { l.bounds[l.bounds.len() - 1].span.hi
l.bounds[l.bounds.len() - 1].span.hi };
}; codemap::mk_sp(l.lifetime.span.lo, hi)
codemap::mk_sp(l.lifetime.span.lo, hi) });
});
let ty_spans = tys.iter().map(span_for_ty_param); let ty_spans = tys.iter().map(span_for_ty_param);
let items = itemize_list(self.codemap, let items = itemize_list(self.codemap,

View file

@ -10,6 +10,7 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(custom_attribute)] #![feature(custom_attribute)]
#![feature(slice_splits)]
#![allow(unused_attributes)] #![allow(unused_attributes)]
// TODO we're going to allocate a whole bunch of temp Strings, is it worth // TODO we're going to allocate a whole bunch of temp Strings, is it worth

View file

@ -269,109 +269,107 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let white_space: &[_] = &[' ', '\t']; let white_space: &[_] = &[' ', '\t'];
self.inner self.inner.next().map(|item| {
.next() let mut new_lines = false;
.map(|item| { // Pre-comment
let mut new_lines = false; let pre_snippet = self.codemap
// Pre-comment .span_to_snippet(codemap::mk_sp(self.prev_span_end,
let pre_snippet = self.codemap (self.get_lo)(&item)))
.span_to_snippet(codemap::mk_sp(self.prev_span_end, .unwrap();
(self.get_lo)(&item))) let trimmed_pre_snippet = pre_snippet.trim();
.unwrap(); let pre_comment = if !trimmed_pre_snippet.is_empty() {
let trimmed_pre_snippet = pre_snippet.trim(); Some(trimmed_pre_snippet.to_owned())
let pre_comment = if !trimmed_pre_snippet.is_empty() { } else {
Some(trimmed_pre_snippet.to_owned()) None
} else { };
None
};
// Post-comment // Post-comment
let next_start = match self.inner.peek() { let next_start = match self.inner.peek() {
Some(ref next_item) => (self.get_lo)(next_item), Some(ref next_item) => (self.get_lo)(next_item),
None => self.next_span_start, None => self.next_span_start,
}; };
let post_snippet = self.codemap let post_snippet = self.codemap
.span_to_snippet(codemap::mk_sp((self.get_hi)(&item), .span_to_snippet(codemap::mk_sp((self.get_hi)(&item),
next_start)) next_start))
.unwrap(); .unwrap();
let comment_end = match self.inner.peek() { let comment_end = match self.inner.peek() {
Some(..) => { Some(..) => {
let block_open_index = post_snippet.find("/*"); let block_open_index = post_snippet.find("/*");
let newline_index = post_snippet.find('\n'); let newline_index = post_snippet.find('\n');
let separator_index = post_snippet.find_uncommented(",").unwrap(); let separator_index = post_snippet.find_uncommented(",").unwrap();
match (block_open_index, newline_index) { match (block_open_index, newline_index) {
// Separator before comment, with the next item on same line. // Separator before comment, with the next item on same line.
// Comment belongs to next item. // Comment belongs to next item.
(Some(i), None) if i > separator_index => { (Some(i), None) if i > separator_index => {
separator_index + 1 separator_index + 1
}
// Block-style post-comment before the separator.
(Some(i), None) => {
cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i,
separator_index + 1)
}
// Block-style post-comment. Either before or after the separator.
(Some(i), Some(j)) if i < j => {
cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i,
separator_index + 1)
}
// Potential *single* line comment.
(_, Some(j)) => j + 1,
_ => post_snippet.len(),
} }
} // Block-style post-comment before the separator.
None => { (Some(i), None) => {
post_snippet.find_uncommented(self.terminator).unwrap_or(post_snippet.len()) cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i,
} separator_index + 1)
}; }
// Block-style post-comment. Either before or after the separator.
if !post_snippet.is_empty() && comment_end > 0 { (Some(i), Some(j)) if i < j => {
// Account for extra whitespace between items. This is fiddly cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i,
// because of the way we divide pre- and post- comments. separator_index + 1)
}
// Everything from the separator to the next item. // Potential *single* line comment.
let test_snippet = &post_snippet[comment_end-1..]; (_, Some(j)) => j + 1,
let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); _ => post_snippet.len(),
// From the end of the first line of comments.
let test_snippet = &test_snippet[first_newline..];
let first = test_snippet.find(|c: char| !c.is_whitespace())
.unwrap_or(test_snippet.len());
// From the end of the first line of comments to the next non-whitespace char.
let test_snippet = &test_snippet[..first];
if test_snippet.chars().filter(|c| c == &'\n').count() > 1 {
// There were multiple line breaks which got trimmed to nothing.
new_lines = true;
} }
} }
None => {
// Cleanup post-comment: strip separators and whitespace. post_snippet.find_uncommented(self.terminator).unwrap_or(post_snippet.len())
self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32);
let post_snippet = post_snippet[..comment_end].trim();
let post_snippet_trimmed = if post_snippet.starts_with(',') {
post_snippet[1..].trim_matches(white_space)
} else if post_snippet.ends_with(",") {
post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space)
} else {
post_snippet
};
let post_comment = if !post_snippet_trimmed.is_empty() {
Some(post_snippet_trimmed.to_owned())
} else {
None
};
ListItem {
pre_comment: pre_comment,
item: (self.get_item_string)(&item),
post_comment: post_comment,
new_lines: new_lines,
} }
}) };
if !post_snippet.is_empty() && comment_end > 0 {
// Account for extra whitespace between items. This is fiddly
// because of the way we divide pre- and post- comments.
// Everything from the separator to the next item.
let test_snippet = &post_snippet[comment_end-1..];
let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len());
// From the end of the first line of comments.
let test_snippet = &test_snippet[first_newline..];
let first = test_snippet.find(|c: char| !c.is_whitespace())
.unwrap_or(test_snippet.len());
// From the end of the first line of comments to the next non-whitespace char.
let test_snippet = &test_snippet[..first];
if test_snippet.chars().filter(|c| c == &'\n').count() > 1 {
// There were multiple line breaks which got trimmed to nothing.
new_lines = true;
}
}
// Cleanup post-comment: strip separators and whitespace.
self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32);
let post_snippet = post_snippet[..comment_end].trim();
let post_snippet_trimmed = if post_snippet.starts_with(',') {
post_snippet[1..].trim_matches(white_space)
} else if post_snippet.ends_with(",") {
post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space)
} else {
post_snippet
};
let post_comment = if !post_snippet_trimmed.is_empty() {
Some(post_snippet_trimmed.to_owned())
} else {
None
};
ListItem {
pre_comment: pre_comment,
item: (self.get_item_string)(&item),
post_comment: post_comment,
new_lines: new_lines,
}
})
} }
} }

View file

@ -130,16 +130,16 @@ impl<'a> Rewrite for SegmentParam<'a> {
// FIXME doesn't always use width, offset // FIXME doesn't always use width, offset
fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
Some(match *self { Some(match *self {
SegmentParam::LifeTime(ref lt) => { SegmentParam::LifeTime(ref lt) => {
pprust::lifetime_to_string(lt) pprust::lifetime_to_string(lt)
} }
SegmentParam::Type(ref ty) => { SegmentParam::Type(ref ty) => {
try_opt!(ty.rewrite(context, width, offset)) try_opt!(ty.rewrite(context, width, offset))
} }
SegmentParam::Binding(ref binding) => { SegmentParam::Binding(ref binding) => {
format!("{} = {}", binding.ident, try_opt!(binding.ty.rewrite(context, width, offset))) format!("{} = {}", binding.ident, try_opt!(binding.ty.rewrite(context, width, offset)))
} }
}) })
} }
} }
@ -368,8 +368,9 @@ impl Rewrite for ast::TyParamBound {
impl Rewrite for ast::TyParamBounds { impl Rewrite for ast::TyParamBounds {
fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
let strs: Vec<_> = let strs: Vec<_> = self.iter()
self.iter().map(|b| b.rewrite(context, width, offset).unwrap()).collect(); .map(|b| b.rewrite(context, width, offset).unwrap())
.collect();
Some(strs.join(" + ")) Some(strs.join(" + "))
} }
} }

View file

@ -21,7 +21,7 @@ enum_trailing_comma = true
report_todo = "Always" report_todo = "Always"
report_fixme = "Never" report_fixme = "Never"
reorder_imports = false reorder_imports = false
expr_indent_style = "Tabbed"
closure_indent_style = "Visual"
single_line_if_else = false single_line_if_else = false
format_strings = true format_strings = true
chains_overflow_last = true
take_source_hints = true

View file

@ -0,0 +1,38 @@
// rustfmt-chains_overflow_last: false
// Test chain formatting without overflowing the last item.
fn main() {
bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc
.ddddddddddddddddddddddddddd();
bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee();
x()
.y(|| match cond() { true => (), false => () });
loong_func()
.quux(move || if true {
1
} else {
2
});
fffffffffffffffffffffffffffffffffff(a,
{
SCRIPT_TASK_ROOT
.with(|root| {
// Another case of write_list failing us.
*root.borrow_mut() = Some(&script_task);
});
});
let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx
.map(|x| x + 5)
.map(|x| x / 2)
.fold(0, |acc, x| acc + x);
aaaaaaaaaaaaaaaa.map(|x| {
x += 1;
x
}).filter(some_mod::some_filter)
}

View file

@ -1,10 +1,10 @@
// Test chain formatting. // Test chain formatting.
fn main() { fn main() {
let a = b.c // Don't put chains on a single list if it wasn't so in source.
.d let a = b .c
.1 .d.1
.foo(|x| x + 1); .foo(|x| x + 1);
bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc
.ddddddddddddddddddddddddddd(); .ddddddddddddddddddddddddddd();
@ -25,7 +25,6 @@ fn main() {
{ {
SCRIPT_TASK_ROOT SCRIPT_TASK_ROOT
.with(|root| { .with(|root| {
// Another case of write_list failing us.
*root.borrow_mut() = Some(&script_task); *root.borrow_mut() = Some(&script_task);
}); });
}); });

View file

@ -0,0 +1,8 @@
// rustfmt-take_source_hints: false
// We know best!
fn main() {
a.b
.c
.d();
}

View file

@ -1,9 +0,0 @@
// rustfmt-expr_indent_style: Visual
// Visual level block indentation.
fn matcher() {
Some(while true {
test();
})
}

View file

@ -165,12 +165,10 @@ fn read_significant_comments(file_name: &str) -> HashMap<String, String> {
.map(|line| line.ok().expect("Failed getting line.")) .map(|line| line.ok().expect("Failed getting line."))
.take_while(|line| line_regex.is_match(&line)) .take_while(|line| line_regex.is_match(&line))
.filter_map(|line| { .filter_map(|line| {
regex.captures_iter(&line) regex.captures_iter(&line).next().map(|capture| {
.next() (capture.at(1).expect("Couldn\'t unwrap capture.").to_owned(),
.map(|capture| { capture.at(2).expect("Couldn\'t unwrap capture.").to_owned())
(capture.at(1).expect("Couldn\'t unwrap capture.").to_owned(), })
capture.at(2).expect("Couldn\'t unwrap capture.").to_owned())
})
}) })
.collect() .collect()
} }

View file

@ -0,0 +1,45 @@
// rustfmt-chains_overflow_last: false
// Test chain formatting without overflowing the last item.
fn main() {
bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd();
bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc
.ddddddddddddddddddddddddddd
.eeeeeeee();
x().y(|| {
match cond() {
true => (),
false => (),
}
});
loong_func()
.quux(move || {
if true {
1
} else {
2
}
});
fffffffffffffffffffffffffffffffffff(a,
{
SCRIPT_TASK_ROOT.with(|root| {
// Another case of write_list failing us.
*root.borrow_mut() = Some(&script_task);
});
});
let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5)
.map(|x| x / 2)
.fold(0,
|acc, x| acc + x);
aaaaaaaaaaaaaaaa.map(|x| {
x += 1;
x
})
.filter(some_mod::some_filter)
}

View file

@ -0,0 +1,16 @@
// rustfmt-chains_overflow_last: false
fn main() {
reader.lines()
.map(|line| line.ok().expect("Failed getting line."))
.take_while(|line| line_regex.is_match(&line))
.filter_map(|line| {
regex.captures_iter(&line)
.next()
.map(|capture| {
(capture.at(1).expect("Couldn\'t unwrap capture.").to_owned(),
capture.at(2).expect("Couldn\'t unwrap capture.").to_owned())
})
})
.collect();
}

View file

@ -1,7 +1,11 @@
// Test chain formatting. // Test chain formatting.
fn main() { fn main() {
let a = b.c.d.1.foo(|x| x + 1); // Don't put chains on a single list if it wasn't so in source.
let a = b.c
.d
.1
.foo(|x| x + 1);
bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd();
@ -10,27 +14,25 @@ fn main() {
.eeeeeeee(); .eeeeeeee();
x().y(|| { x().y(|| {
match cond() { match cond() {
true => (), true => (),
false => (), false => (),
} }
}); });
loong_func() loong_func().quux(move || {
.quux(move || { if true {
if true { 1
1 } else {
} else { 2
2 }
} });
});
fffffffffffffffffffffffffffffffffff(a, fffffffffffffffffffffffffffffffffff(a,
{ {
SCRIPT_TASK_ROOT.with(|root| { SCRIPT_TASK_ROOT.with(|root| {
// Another case of write_list failing us. *root.borrow_mut() = Some(&script_task);
*root.borrow_mut() = Some(&script_task); });
});
}); });
let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5)

View file

@ -0,0 +1,6 @@
// rustfmt-take_source_hints: false
// We know best!
fn main() {
a.b.c.d();
}

View file

@ -1,9 +0,0 @@
// rustfmt-expr_indent_style: Visual
// Visual level block indentation.
fn matcher() {
Some(while true {
test();
})
}