Format async closure

This commit is contained in:
Seiichi Uchida 2018-07-09 23:20:53 +09:00
parent ae2c6a6692
commit 60ce411b53
5 changed files with 33 additions and 11 deletions

View File

@ -31,9 +31,9 @@ use utils::{last_line_width, left_most_sub_expr, stmt_expr};
// statement without needing a semi-colon), then adding or removing braces
// can change whether it is treated as an expression or statement.
// FIXME(topecongiro) Format async closures (#2813).
pub fn rewrite_closure(
capture: ast::CaptureBy,
asyncness: ast::IsAsync,
movability: ast::Movability,
fn_decl: &ast::FnDecl,
body: &ast::Expr,
@ -43,8 +43,9 @@ pub fn rewrite_closure(
) -> Option<String> {
debug!("rewrite_closure {:?}", body);
let (prefix, extra_offset) =
rewrite_closure_fn_decl(capture, movability, fn_decl, body, span, context, shape)?;
let (prefix, extra_offset) = rewrite_closure_fn_decl(
capture, asyncness, movability, fn_decl, body, span, context, shape,
)?;
// 1 = space between `|...|` and body.
let body_shape = shape.offset_left(extra_offset)?;
@ -198,6 +199,7 @@ fn rewrite_closure_block(
// Return type is (prefix, extra_offset)
fn rewrite_closure_fn_decl(
capture: ast::CaptureBy,
asyncness: ast::IsAsync,
movability: ast::Movability,
fn_decl: &ast::FnDecl,
body: &ast::Expr,
@ -205,12 +207,12 @@ fn rewrite_closure_fn_decl(
context: &RewriteContext,
shape: Shape,
) -> Option<(String, usize)> {
let is_async = if asyncness.is_async() { "async " } else { "" };
let mover = if capture == ast::CaptureBy::Value {
"move "
} else {
""
};
let immovable = if movability == ast::Movability::Static {
"static "
} else {
@ -219,7 +221,7 @@ fn rewrite_closure_fn_decl(
// 4 = "|| {".len(), which is overconservative when the closure consists of
// a single expression.
let nested_shape = shape
.shrink_left(mover.len() + immovable.len())?
.shrink_left(is_async.len() + mover.len() + immovable.len())?
.sub_width(4)?;
// 1 = |
@ -265,7 +267,7 @@ fn rewrite_closure_fn_decl(
config: context.config,
};
let list_str = write_list(&item_vec, &fmt)?;
let mut prefix = format!("{}{}|{}|", immovable, mover, list_str);
let mut prefix = format!("{}{}{}|{}|", is_async, immovable, mover, list_str);
if !ret_str.is_empty() {
if prefix.contains('\n') {
@ -289,7 +291,9 @@ pub fn rewrite_last_closure(
expr: &ast::Expr,
shape: Shape,
) -> Option<String> {
if let ast::ExprKind::Closure(capture, _, movability, ref fn_decl, ref body, _) = expr.node {
if let ast::ExprKind::Closure(capture, asyncness, movability, ref fn_decl, ref body, _) =
expr.node
{
let body = match body.node {
ast::ExprKind::Block(ref block, _)
if !is_unsafe_block(block)
@ -300,7 +304,7 @@ pub fn rewrite_last_closure(
_ => body,
};
let (prefix, extra_offset) = rewrite_closure_fn_decl(
capture, movability, fn_decl, body, expr.span, context, shape,
capture, asyncness, movability, fn_decl, body, expr.span, context, shape,
)?;
// If the closure goes multi line before its body, do not overflow the closure.
if prefix.contains('\n') {

View File

@ -104,6 +104,7 @@ create_config! {
"Maximum number of blank lines which can be put between items.";
blank_lines_lower_bound: usize, 0, false,
"Minimum number of blank lines which must be put between items.";
edition: Edition, Edition::Edition2015, false, "The edition of the parser. (RFC 2052)";
// Options that can change the source code beyond whitespace/blocks (somewhat linty things)
merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";
@ -111,7 +112,7 @@ create_config! {
use_field_init_shorthand: bool, false, true, "Use field initialization shorthand if possible";
force_explicit_abi: bool, true, true, "Always print the abi for extern items";
condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \
in tuple patterns";
in tuple patterns";
// Control options (changes the operation of rustfmt, rather than the formatting)
color: Color, Color::Auto, false,

View File

@ -340,3 +340,18 @@ pub trait CliOptions {
fn apply_to(self, config: &mut Config);
fn config_path(&self) -> Option<&Path>;
}
/// The edition of the compiler (RFC 2052)
configuration_option_enum!{ Edition:
Edition2015,
Edition2018,
}
impl Edition {
pub(crate) fn to_libsyntax_pos_edition(&self) -> syntax_pos::edition::Edition {
match self {
Edition::Edition2015 => syntax_pos::edition::Edition::Edition2015,
Edition::Edition2018 => syntax_pos::edition::Edition::Edition2018,
}
}
}

View File

@ -183,9 +183,9 @@ pub fn format_expr(
} else {
Some("yield".to_string())
},
ast::ExprKind::Closure(capture, _, movability, ref fn_decl, ref body, _) => {
ast::ExprKind::Closure(capture, asyncness, movability, ref fn_decl, ref body, _) => {
closures::rewrite_closure(
capture, movability, fn_decl, body, expr.span, context, shape,
capture, asyncness, movability, fn_decl, body, expr.span, context, shape,
)
}
ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) => {

View File

@ -33,6 +33,7 @@ extern crate serde;
extern crate serde_derive;
extern crate serde_json;
extern crate syntax;
extern crate syntax_pos;
extern crate toml;
extern crate unicode_segmentation;
@ -793,6 +794,7 @@ fn format_input_inner<T: Write>(
config: &Config,
mut out: Option<&mut T>,
) -> Result<(Summary, FileMap, FormatReport), (ErrorKind, Summary)> {
syntax_pos::hygiene::set_default_edition(config.edition().to_libsyntax_pos_edition());
let mut summary = Summary::default();
if config.disable_all_formatting() {
// When the input is from stdin, echo back the input.