Format closures' return types
This commit is contained in:
parent
db79a5aec5
commit
582aa4f2fe
4 changed files with 85 additions and 32 deletions
58
src/expr.rs
58
src/expr.rs
|
@ -163,9 +163,12 @@ fn rewrite_closure(capture: ast::CaptureClause,
|
||||||
|
|
||||||
// 4 = "|| {".len(), which is overconservative when the closure consists of
|
// 4 = "|| {".len(), which is overconservative when the closure consists of
|
||||||
// a single expression.
|
// a single expression.
|
||||||
let argument_budget = try_opt!(width.checked_sub(4 + mover.len()));
|
let budget = try_opt!(width.checked_sub(4 + mover.len()));
|
||||||
// 1 = |
|
// 1 = |
|
||||||
let argument_offset = offset + 1;
|
let argument_offset = offset + 1;
|
||||||
|
let ret_str = try_opt!(fn_decl.output.rewrite(context, budget, argument_offset));
|
||||||
|
// 1 = space between arguments and return type.
|
||||||
|
let horizontal_budget = budget.checked_sub(ret_str.len() + 1).unwrap_or(0);
|
||||||
|
|
||||||
let arg_items = itemize_list(context.codemap,
|
let arg_items = itemize_list(context.codemap,
|
||||||
fn_decl.inputs.iter(),
|
fn_decl.inputs.iter(),
|
||||||
|
@ -176,13 +179,37 @@ fn rewrite_closure(capture: ast::CaptureClause,
|
||||||
span_after(span, "|", context.codemap),
|
span_after(span, "|", context.codemap),
|
||||||
body.span.lo);
|
body.span.lo);
|
||||||
|
|
||||||
let fmt = ListFormatting::for_fn(argument_budget, argument_offset);
|
let fmt = ListFormatting {
|
||||||
|
tactic: ListTactic::HorizontalVertical,
|
||||||
|
separator: ",",
|
||||||
|
trailing_separator: SeparatorTactic::Never,
|
||||||
|
indent: argument_offset,
|
||||||
|
h_width: horizontal_budget,
|
||||||
|
v_width: budget,
|
||||||
|
ends_with_newline: false,
|
||||||
|
};
|
||||||
let list_str = try_opt!(write_list(&arg_items.collect::<Vec<_>>(), &fmt));
|
let list_str = try_opt!(write_list(&arg_items.collect::<Vec<_>>(), &fmt));
|
||||||
let prefix = format!("{}|{}|", mover, list_str);
|
let mut prefix = format!("{}|{}|", mover, list_str);
|
||||||
|
|
||||||
|
if !ret_str.is_empty() {
|
||||||
|
if prefix.contains('\n') {
|
||||||
|
prefix.push('\n');
|
||||||
|
prefix.push_str(&make_indent(argument_offset));
|
||||||
|
} else {
|
||||||
|
prefix.push(' ');
|
||||||
|
}
|
||||||
|
prefix.push_str(&ret_str);
|
||||||
|
}
|
||||||
|
|
||||||
let closure_indent = closure_indent(context, offset);
|
let closure_indent = closure_indent(context, offset);
|
||||||
|
|
||||||
// Try to format closure body as a single line expression without braces.
|
// Try to format closure body as a single line expression without braces.
|
||||||
if body.stmts.is_empty() {
|
if is_simple_block(body, context.codemap) && !prefix.contains('\n') {
|
||||||
|
let (spacer, closer) = if ret_str.is_empty() {
|
||||||
|
(" ", "")
|
||||||
|
} else {
|
||||||
|
(" { ", " }")
|
||||||
|
};
|
||||||
let expr = body.expr.as_ref().unwrap();
|
let expr = body.expr.as_ref().unwrap();
|
||||||
// All closure bodies are blocks in the eyes of the AST, but we may not
|
// All closure bodies are blocks in the eyes of the AST, but we may not
|
||||||
// want to unwrap them when they only contain a single expression.
|
// want to unwrap them when they only contain a single expression.
|
||||||
|
@ -192,28 +219,31 @@ fn rewrite_closure(capture: ast::CaptureClause,
|
||||||
}
|
}
|
||||||
_ => expr,
|
_ => expr,
|
||||||
};
|
};
|
||||||
|
let extra_offset = extra_offset(&prefix, offset) + spacer.len();
|
||||||
// 1 = the separating space between arguments and the body.
|
let budget = try_opt!(width.checked_sub(extra_offset + closer.len()));
|
||||||
let extra_offset = extra_offset(&prefix, offset) + 1;
|
|
||||||
let budget = try_opt!(width.checked_sub(extra_offset));
|
|
||||||
let rewrite = inner_expr.rewrite(context, budget, offset + extra_offset);
|
let rewrite = inner_expr.rewrite(context, budget, offset + extra_offset);
|
||||||
|
|
||||||
// Checks if rewrite succeeded and fits on a single line.
|
// Checks if rewrite succeeded and fits on a single line.
|
||||||
let accept_rewrite = rewrite.as_ref().map(|result| !result.contains('\n')).unwrap_or(false);
|
let accept_rewrite = rewrite.as_ref().map(|result| !result.contains('\n')).unwrap_or(false);
|
||||||
|
|
||||||
if accept_rewrite {
|
if accept_rewrite {
|
||||||
return Some(format!("{} {}", prefix, rewrite.unwrap()));
|
return Some(format!("{}{}{}{}", prefix, spacer, rewrite.unwrap(), closer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We couldn't format the closure body as a single line expression; fall
|
// We couldn't format the closure body as a single line expression; fall
|
||||||
// back to block formatting.
|
// back to block formatting.
|
||||||
let inner_context = context.overflow_context(closure_indent - context.block_indent);
|
let inner_context = context.overflow_context(closure_indent - context.block_indent);
|
||||||
let body_rewrite = if let ast::Expr_::ExprBlock(ref inner) = body.expr.as_ref().unwrap().node {
|
let body_rewrite = body.expr
|
||||||
inner.rewrite(&inner_context, 0, 0)
|
.as_ref()
|
||||||
} else {
|
.and_then(|body_expr| {
|
||||||
body.rewrite(&inner_context, 0, 0)
|
if let ast::Expr_::ExprBlock(ref inner) = body_expr.node {
|
||||||
};
|
Some(inner.rewrite(&inner_context, 2, 0))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| body.rewrite(&inner_context, 2, 0));
|
||||||
|
|
||||||
Some(format!("{} {}", prefix, try_opt!(body_rewrite)))
|
Some(format!("{} {}", prefix, try_opt!(body_rewrite)))
|
||||||
}
|
}
|
||||||
|
|
25
src/items.rs
25
src/items.rs
|
@ -17,7 +17,7 @@ use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic,
|
||||||
use expr::rewrite_assign_rhs;
|
use expr::rewrite_assign_rhs;
|
||||||
use comment::FindUncommented;
|
use comment::FindUncommented;
|
||||||
use visitor::FmtVisitor;
|
use visitor::FmtVisitor;
|
||||||
use rewrite::Rewrite;
|
use rewrite::{Rewrite, RewriteContext};
|
||||||
use config::{Config, BlockIndentStyle, Density};
|
use config::{Config, BlockIndentStyle, Density};
|
||||||
|
|
||||||
use syntax::{ast, abi};
|
use syntax::{ast, abi};
|
||||||
|
@ -207,7 +207,8 @@ impl<'a> FmtVisitor<'a> {
|
||||||
generics_span));
|
generics_span));
|
||||||
result.push_str(&generics_str);
|
result.push_str(&generics_str);
|
||||||
|
|
||||||
let ret_str = self.rewrite_return(&fd.output, indent);
|
let context = self.get_context();
|
||||||
|
let ret_str = fd.output.rewrite(&context, self.config.max_width - indent, indent).unwrap();
|
||||||
|
|
||||||
// Args.
|
// Args.
|
||||||
let (one_line_budget, multi_line_budget, mut arg_indent) =
|
let (one_line_budget, multi_line_budget, mut arg_indent) =
|
||||||
|
@ -902,14 +903,22 @@ impl<'a> FmtVisitor<'a> {
|
||||||
Some(format!(" where {}", preds_str))
|
Some(format!(" where {}", preds_str))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn rewrite_return(&self, ret: &ast::FunctionRetTy, indent: usize) -> String {
|
impl Rewrite for ast::FunctionRetTy {
|
||||||
match *ret {
|
fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
|
||||||
ast::FunctionRetTy::DefaultReturn(_) => String::new(),
|
match *self {
|
||||||
ast::FunctionRetTy::NoReturn(_) => "-> !".to_owned(),
|
ast::FunctionRetTy::DefaultReturn(_) => Some(String::new()),
|
||||||
|
ast::FunctionRetTy::NoReturn(_) => {
|
||||||
|
if width >= 4 {
|
||||||
|
Some("-> !".to_owned())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
ast::FunctionRetTy::Return(ref ty) => {
|
ast::FunctionRetTy::Return(ref ty) => {
|
||||||
let ctxt = &self.get_context();
|
let inner_width = try_opt!(width.checked_sub(3));
|
||||||
format!("-> {}", ty.rewrite(ctxt, ctxt.config.max_width, indent).unwrap())
|
ty.rewrite(context, inner_width, offset + 3).map(|r| format!("-> {}", r))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let square = ( |i: i32 | i * i );
|
let square = ( |i: i32 | i * i );
|
||||||
|
|
||||||
let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ |
|
|
||||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb);
|
|
||||||
|
|
||||||
let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ |
|
let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ |
|
||||||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb);
|
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb);
|
||||||
|
|
||||||
|
@ -28,12 +25,22 @@ fn main() {
|
||||||
|
|
||||||
let empty = |arg| {};
|
let empty = |arg| {};
|
||||||
|
|
||||||
|
let simple = |arg| { /* TODO(#27): comment formatting */ foo(arg) };
|
||||||
|
|
||||||
let test = | | { do_something(); do_something_else(); };
|
let test = | | { do_something(); do_something_else(); };
|
||||||
|
|
||||||
let arg_test = |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame();
|
let arg_test = |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame();
|
||||||
|
|
||||||
let arg_test = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()};
|
let arg_test = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()};
|
||||||
|
|
||||||
|
let simple_closure = move || -> () {};
|
||||||
|
|
||||||
|
let closure = |input: Ty| -> Option<String> {
|
||||||
|
foo()
|
||||||
|
};
|
||||||
|
|
||||||
|
let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() };
|
||||||
|
|
||||||
|arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3;
|
|arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3;
|
||||||
arg2 * arg1 - temp }
|
arg2 * arg1 - temp }
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,6 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let square = (|i: i32| i * i);
|
let square = (|i: i32| i * i);
|
||||||
|
|
||||||
let commented = |// first
|
|
||||||
a, // argument
|
|
||||||
// second
|
|
||||||
b: WithType, // argument
|
|
||||||
// ignored
|
|
||||||
_| (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb);
|
|
||||||
|
|
||||||
let commented = |// first
|
let commented = |// first
|
||||||
a, // argument
|
a, // argument
|
||||||
// second
|
// second
|
||||||
|
@ -46,6 +39,10 @@ fn main() {
|
||||||
|
|
||||||
let empty = |arg| {};
|
let empty = |arg| {};
|
||||||
|
|
||||||
|
let simple = |arg| { /* TODO(#27): comment formatting */
|
||||||
|
foo(arg)
|
||||||
|
};
|
||||||
|
|
||||||
let test = || {
|
let test = || {
|
||||||
do_something();
|
do_something();
|
||||||
do_something_else();
|
do_something_else();
|
||||||
|
@ -59,6 +56,16 @@ fn main() {
|
||||||
looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()
|
looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let simple_closure = move || -> () {};
|
||||||
|
|
||||||
|
let closure = |input: Ty| -> Option<String> { foo() };
|
||||||
|
|
||||||
|
let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1,
|
||||||
|
aaaaaaaaaaaaaaaaaaaaaaarg2|
|
||||||
|
-> Strong {
|
||||||
|
"sup".to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|arg1, arg2, _, _, arg3, arg4| {
|
|arg1, arg2, _, _, arg3, arg4| {
|
||||||
let temp = arg4 + arg3;
|
let temp = arg4 + arg3;
|
||||||
arg2 * arg1 - temp
|
arg2 * arg1 - temp
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue