diff options
| author | Nick Cameron <nrc@ncameron.org> | 2015-09-09 09:14:15 +1200 |
|---|---|---|
| committer | Nick Cameron <nrc@ncameron.org> | 2015-09-09 09:14:15 +1200 |
| commit | aa2abc63a0adf69ce72ff25cba1fb384bfb73600 (patch) | |
| tree | ec02e52d856f255156d8c5d5e3686c561ebfb007 /src | |
| parent | db79a5aec5055b58c5f8f576adc1aa551087bce6 (diff) | |
| parent | 582aa4f2fed9ab3e6bcfe4112c20cae42a5570e0 (diff) | |
Merge pull request #288 from marcusklaas/closure-return
Format closures' return types
Diffstat (limited to 'src')
| -rw-r--r-- | src/expr.rs | 58 | ||||
| -rw-r--r-- | src/items.rs | 25 |
2 files changed, 61 insertions, 22 deletions
diff --git a/src/expr.rs b/src/expr.rs index 2923aa45097..ab20dc1738d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -163,9 +163,12 @@ fn rewrite_closure(capture: ast::CaptureClause, // 4 = "|| {".len(), which is overconservative when the closure consists of // 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 = | 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, fn_decl.inputs.iter(), @@ -176,13 +179,37 @@ fn rewrite_closure(capture: ast::CaptureClause, span_after(span, "|", context.codemap), 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 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); // 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(); // 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. @@ -192,28 +219,31 @@ fn rewrite_closure(capture: ast::CaptureClause, } _ => expr, }; - - // 1 = the separating space between arguments and the body. - let extra_offset = extra_offset(&prefix, offset) + 1; - let budget = try_opt!(width.checked_sub(extra_offset)); + let extra_offset = extra_offset(&prefix, offset) + spacer.len(); + let budget = try_opt!(width.checked_sub(extra_offset + closer.len())); let rewrite = inner_expr.rewrite(context, budget, offset + extra_offset); // Checks if rewrite succeeded and fits on a single line. let accept_rewrite = rewrite.as_ref().map(|result| !result.contains('\n')).unwrap_or(false); 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 // back to block formatting. 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 { - inner.rewrite(&inner_context, 0, 0) - } else { - body.rewrite(&inner_context, 0, 0) - }; + let body_rewrite = body.expr + .as_ref() + .and_then(|body_expr| { + 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))) } diff --git a/src/items.rs b/src/items.rs index e2224ce4eff..7555ea01199 100644 --- a/src/items.rs +++ b/src/items.rs @@ -17,7 +17,7 @@ use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, use expr::rewrite_assign_rhs; use comment::FindUncommented; use visitor::FmtVisitor; -use rewrite::Rewrite; +use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density}; use syntax::{ast, abi}; @@ -207,7 +207,8 @@ impl<'a> FmtVisitor<'a> { generics_span)); 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. let (one_line_budget, multi_line_budget, mut arg_indent) = @@ -902,14 +903,22 @@ impl<'a> FmtVisitor<'a> { Some(format!(" where {}", preds_str)) } } +} - fn rewrite_return(&self, ret: &ast::FunctionRetTy, indent: usize) -> String { - match *ret { - ast::FunctionRetTy::DefaultReturn(_) => String::new(), - ast::FunctionRetTy::NoReturn(_) => "-> !".to_owned(), +impl Rewrite for ast::FunctionRetTy { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> { + match *self { + ast::FunctionRetTy::DefaultReturn(_) => Some(String::new()), + ast::FunctionRetTy::NoReturn(_) => { + if width >= 4 { + Some("-> !".to_owned()) + } else { + None + } + } ast::FunctionRetTy::Return(ref ty) => { - let ctxt = &self.get_context(); - format!("-> {}", ty.rewrite(ctxt, ctxt.config.max_width, indent).unwrap()) + let inner_width = try_opt!(width.checked_sub(3)); + ty.rewrite(context, inner_width, offset + 3).map(|r| format!("-> {}", r)) } } } |
