From 60ce411b5310c8af09de2d552e67b0593f3f1d4b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 9 Jul 2018 23:20:53 +0900 Subject: [PATCH] Format async closure --- src/closures.rs | 20 ++++++++++++-------- src/config/mod.rs | 3 ++- src/config/options.rs | 15 +++++++++++++++ src/expr.rs | 4 ++-- src/lib.rs | 2 ++ 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/closures.rs b/src/closures.rs index 5f1102a36fca..5e2f01053f11 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -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 { 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 { - 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') { diff --git a/src/config/mod.rs b/src/config/mod.rs index 71bdefeea79c..fcda529ea893 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -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, diff --git a/src/config/options.rs b/src/config/options.rs index b3599c230f45..5fa0a0483136 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -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, + } + } +} diff --git a/src/expr.rs b/src/expr.rs index ca31b0b82ef0..6928b77f3603 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -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(..) => { diff --git a/src/lib.rs b/src/lib.rs index 114e72c4847b..817ed426e522 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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( 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.