]> git.lizzy.rs Git - rust.git/commitdiff
Implement combining openings and closings
authortopecongiro <seuchida@gmail.com>
Sun, 21 May 2017 10:56:13 +0000 (19:56 +0900)
committertopecongiro <seuchida@gmail.com>
Tue, 23 May 2017 03:45:09 +0000 (12:45 +0900)
src/expr.rs

index 9c4f48bbb7e63d4d83fbc59edc1894e5e4c25f30..f0db88ae56679a216018b2cb82bc1b9ae8ce6cc8 100644 (file)
@@ -1334,18 +1334,21 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
 
         let pats_str = format!("{}{}", pats_str, guard_str);
 
 
         let pats_str = format!("{}{}", pats_str, guard_str);
 
-        let body = match body.node {
+        let (mut extend, body) = match body.node {
             ast::ExprKind::Block(ref block) if !is_unsafe_block(block) &&
                                                is_simple_block(block, context.codemap) &&
                                                context.config.wrap_match_arms() => {
                 if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node {
             ast::ExprKind::Block(ref block) if !is_unsafe_block(block) &&
                                                is_simple_block(block, context.codemap) &&
                                                context.config.wrap_match_arms() => {
                 if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node {
-                    expr
+                    (false, &**expr)
                 } else {
                 } else {
-                    &**body
+                    (false, &**body)
                 }
             }
                 }
             }
-            _ => &**body,
+            ast::ExprKind::Call(_, ref args) => (args.len() == 1, &**body),
+            ast::ExprKind::Closure(..) => (true, &**body),
+            _ => (false, &**body),
         };
         };
+        extend &= context.config.fn_call_style == IndentStyle::Block;
 
         let comma = arm_comma(&context.config, body);
         let alt_block_sep = String::from("\n") +
 
         let comma = arm_comma(&context.config, body);
         let alt_block_sep = String::from("\n") +
@@ -1371,6 +1374,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                 Some(ref body_str) if (!body_str.contains('\n') &&
                                        body_str.len() <= arm_shape.width) ||
                                       !context.config.wrap_match_arms() ||
                 Some(ref body_str) if (!body_str.contains('\n') &&
                                        body_str.len() <= arm_shape.width) ||
                                       !context.config.wrap_match_arms() ||
+                                      (extend && first_line_width(body_str) <= arm_shape.width) ||
                                       is_block => {
                     let block_sep = match context.config.control_brace_style() {
                         ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(),
                                       is_block => {
                     let block_sep = match context.config.control_brace_style() {
                         ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(),
@@ -1611,9 +1615,7 @@ pub fn rewrite_call<R>(context: &RewriteContext,
     let closure =
         |callee_max_width| rewrite_call_inner(context, callee, callee_max_width, args, span, shape);
 
     let closure =
         |callee_max_width| rewrite_call_inner(context, callee, callee_max_width, args, span, shape);
 
-    // 2 is for parens
-    let max_width = try_opt!(shape.width.checked_sub(2));
-    binary_search(1, max_width, closure)
+    binary_search(1, shape.width, closure)
 }
 
 fn rewrite_call_inner<R>(context: &RewriteContext,
 }
 
 fn rewrite_call_inner<R>(context: &RewriteContext,
@@ -1635,25 +1637,43 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
         .rewrite(context, callee_shape)
         .ok_or(Ordering::Greater)?;
 
         .rewrite(context, callee_shape)
         .ok_or(Ordering::Greater)?;
 
-    // 4 = `(  )`, 2 = `()`
+    // 2 = `( `, 1 = `(`
     let paren_overhead = if context.config.spaces_within_parens() {
     let paren_overhead = if context.config.spaces_within_parens() {
-        4
-    } else {
         2
         2
+    } else {
+        1
     };
     let used_width = extra_offset(&callee_str, shape);
     let one_line_width = shape
         .width
     };
     let used_width = extra_offset(&callee_str, shape);
     let one_line_width = shape
         .width
-        .checked_sub(used_width + paren_overhead)
+        .checked_sub(used_width + 2 * paren_overhead)
         .ok_or(Ordering::Greater)?;
 
         .ok_or(Ordering::Greater)?;
 
+    // Try combining openings and closings
+    if args.len() == 1 && context.config.fn_call_style() == IndentStyle::Block {
+        let expr = &*args[0];
+        match expr.node {
+            ast::ExprKind::Struct(..) |
+            ast::ExprKind::Call(..) |
+            ast::ExprKind::Closure(..) => {
+                let max_width = min(one_line_width, context.config.fn_call_width());
+                let shape = Shape::legacy(max_width, shape.block().indent);
+                if let Some(expr_str) = expr.rewrite(context, shape) {
+                    if first_line_width(&expr_str) <= max_width {
+                        return Ok(format!("{}({})", callee_str, expr_str));
+                    }
+                }
+            }
+            _ => (),
+        }
+    }
+
     let nested_shape = match context.config.fn_call_style() {
             IndentStyle::Block => shape.block().block_left(context.config.tab_spaces()),
     let nested_shape = match context.config.fn_call_style() {
             IndentStyle::Block => shape.block().block_left(context.config.tab_spaces()),
-            // 1 = (
             IndentStyle::Visual => {
                 shape
             IndentStyle::Visual => {
                 shape
-                    .visual_indent(used_width + 1)
-                    .sub_width(used_width + paren_overhead)
+                    .visual_indent(used_width + paren_overhead)
+                    .sub_width(used_width + 2 * paren_overhead)
             }
         }
         .ok_or(Ordering::Greater)?;
             }
         }
         .ok_or(Ordering::Greater)?;
@@ -1664,8 +1684,12 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
     let list_str = rewrite_call_args(context, args, span, nested_shape, one_line_width)
         .ok_or(Ordering::Less)?;
 
     let list_str = rewrite_call_args(context, args, span, nested_shape, one_line_width)
         .ok_or(Ordering::Less)?;
 
+    let arg_one_line_budget = min(one_line_width, context.config.fn_call_width());
     let result = if context.config.fn_call_style() == IndentStyle::Visual ||
     let result = if context.config.fn_call_style() == IndentStyle::Visual ||
-                    (!list_str.contains('\n') && list_str.chars().last().unwrap_or(' ') != ',') {
+                    (((can_be_overflowed(args) &&
+                       first_line_width(&list_str) <= arg_one_line_budget) ||
+                      !list_str.contains('\n')) &&
+                     list_str.chars().last().unwrap_or(' ') != ',') {
         if context.config.spaces_within_parens() && list_str.len() > 0 {
             format!("{}( {} )", callee_str, list_str)
         } else {
         if context.config.spaces_within_parens() && list_str.len() > 0 {
             format!("{}( {} )", callee_str, list_str)
         } else {
@@ -1682,6 +1706,15 @@ fn rewrite_call_inner<R>(context: &RewriteContext,
     Ok(result)
 }
 
     Ok(result)
 }
 
+fn can_be_overflowed(args: &[ptr::P<ast::Expr>]) -> bool {
+    match args.last().map(|x| &x.node) {
+        Some(&ast::ExprKind::Closure(..)) |
+        Some(&ast::ExprKind::Block(..)) |
+        Some(&ast::ExprKind::Match(..)) if args.len() > 1 => true,
+        _ => false,
+    }
+}
+
 fn rewrite_call_args(context: &RewriteContext,
                      args: &[ptr::P<ast::Expr>],
                      span: Span,
 fn rewrite_call_args(context: &RewriteContext,
                      args: &[ptr::P<ast::Expr>],
                      span: Span,
@@ -1703,12 +1736,7 @@ fn rewrite_call_args(context: &RewriteContext,
     // Try letting the last argument overflow to the next line with block
     // indentation. If its first line fits on one line with the other arguments,
     // we format the function arguments horizontally.
     // Try letting the last argument overflow to the next line with block
     // indentation. If its first line fits on one line with the other arguments,
     // we format the function arguments horizontally.
-    let overflow_last = match args.last().map(|x| &x.node) {
-        Some(&ast::ExprKind::Closure(..)) |
-        Some(&ast::ExprKind::Block(..)) |
-        Some(&ast::ExprKind::Match(..)) if arg_count > 1 => true,
-        _ => false,
-    };
+    let overflow_last = can_be_overflowed(args);
 
     let mut orig_last = None;
     let mut placeholder = None;
 
     let mut orig_last = None;
     let mut placeholder = None;
@@ -1716,11 +1744,16 @@ fn rewrite_call_args(context: &RewriteContext,
     // Replace the last item with its first line to see if it fits with
     // first arguments.
     if overflow_last {
     // Replace the last item with its first line to see if it fits with
     // first arguments.
     if overflow_last {
-        let nested_shape = Shape {
-            indent: shape.indent.block_only(),
-            ..shape
+        let last_arg = args.last().unwrap();
+        let arg_shape = match last_arg.node {
+            ast::ExprKind::Closure(..) if context.config.fn_call_style == IndentStyle::Block => {
+                let mut arg_shape = shape.block();
+                arg_shape.indent.block_indent -= context.config.tab_spaces;
+                arg_shape
+            }
+            _ => shape.block(),
         };
         };
-        let rewrite = args.last().unwrap().rewrite(context, nested_shape);
+        let rewrite = args.last().unwrap().rewrite(context, arg_shape);
 
         if let Some(rewrite) = rewrite {
             let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned());
 
         if let Some(rewrite) = rewrite {
             let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned());