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

View file

@ -104,6 +104,7 @@ create_config! {
"Maximum number of blank lines which can be put between items."; "Maximum number of blank lines which can be put between items.";
blank_lines_lower_bound: usize, 0, false, blank_lines_lower_bound: usize, 0, false,
"Minimum number of blank lines which must be put between items."; "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) // 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"; merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";

View file

@ -340,3 +340,18 @@ pub trait CliOptions {
fn apply_to(self, config: &mut Config); fn apply_to(self, config: &mut Config);
fn config_path(&self) -> Option<&Path>; 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 { } else {
Some("yield".to_string()) 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( 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(..) => { 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_derive;
extern crate serde_json; extern crate serde_json;
extern crate syntax; extern crate syntax;
extern crate syntax_pos;
extern crate toml; extern crate toml;
extern crate unicode_segmentation; extern crate unicode_segmentation;
@ -793,6 +794,7 @@ fn format_input_inner<T: Write>(
config: &Config, config: &Config,
mut out: Option<&mut T>, mut out: Option<&mut T>,
) -> Result<(Summary, FileMap, FormatReport), (ErrorKind, Summary)> { ) -> Result<(Summary, FileMap, FormatReport), (ErrorKind, Summary)> {
syntax_pos::hygiene::set_default_edition(config.edition().to_libsyntax_pos_edition());
let mut summary = Summary::default(); let mut summary = Summary::default();
if config.disable_all_formatting() { if config.disable_all_formatting() {
// When the input is from stdin, echo back the input. // When the input is from stdin, echo back the input.