]> git.lizzy.rs Git - rust.git/blobdiff - src/overflow.rs
Disallow combining a method call with prefix or suffix
[rust.git] / src / overflow.rs
index 6383d032273bdf4e4bcab637137b8d5ffd9f9417..f2f05d835ff0b6eed2571a453ba6491b4a23f074 100644 (file)
 
 use closures;
 use codemap::SpanUtils;
-use expr::{is_every_expr_simple, is_nested_call, maybe_get_args_offset, ToExpr};
+use expr::{is_every_expr_simple, is_method_call, is_nested_call, maybe_get_args_offset, ToExpr};
 use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator};
 use rewrite::{Rewrite, RewriteContext};
 use shape::Shape;
 use spanned::Spanned;
-use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp, paren_overhead};
+use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp};
 
 use std::cmp::min;
 
@@ -138,29 +138,16 @@ pub fn new(
         force_separator_tactic: Option<SeparatorTactic>,
         custom_delims: Option<(&'a str, &'a str)>,
     ) -> Context<'a, T> {
-        // 2 = `( `, 1 = `(`
-        let paren_overhead = if context.config.spaces_within_parens_and_brackets() {
-            2
-        } else {
-            1
-        };
         let used_width = extra_offset(ident, shape);
-        let one_line_width = shape
-            .width
-            .checked_sub(used_width + 2 * paren_overhead)
-            .unwrap_or(0);
+        // 1 = `()`
+        let one_line_width = shape.width.saturating_sub(used_width + 2);
 
         // 1 = "(" or ")"
         let one_line_shape = shape
             .offset_left(last_line_width(ident) + 1)
             .and_then(|shape| shape.sub_width(1))
             .unwrap_or(Shape { width: 0, ..shape });
-        let nested_shape = shape_from_indent_style(
-            context,
-            shape,
-            used_width + 2 * paren_overhead,
-            used_width + paren_overhead,
-        );
+        let nested_shape = shape_from_indent_style(context, shape, used_width + 2, used_width + 1);
         Context {
             context,
             items,
@@ -182,7 +169,8 @@ fn last_item(&self) -> Option<&&T> {
     }
 
     fn items_span(&self) -> Span {
-        let span_lo = self.context
+        let span_lo = self
+            .context
             .snippet_provider
             .span_after(self.span, self.prefix);
         mk_sp(span_lo, self.span.hi())
@@ -233,7 +221,8 @@ fn default_tactic(&self, list_items: &[ListItem]) -> DefinitiveListTactic {
 
     fn try_overflow_last_item(&self, list_items: &mut Vec<ListItem>) -> DefinitiveListTactic {
         // 1 = "("
-        let combine_arg_with_callee = self.items.len() == 1 && self.items[0].to_expr().is_some()
+        let combine_arg_with_callee = self.items.len() == 1
+            && self.items[0].to_expr().is_some()
             && self.ident.len() + 1 <= self.context.config.tab_spaces();
         let overflow_last = combine_arg_with_callee || can_be_overflowed(self.context, self.items);
 
@@ -242,8 +231,8 @@ fn try_overflow_last_item(&self, list_items: &mut Vec<ListItem>) -> DefinitiveLi
         let placeholder = if overflow_last {
             let old_value = *self.context.force_one_line_chain.borrow();
             if !combine_arg_with_callee {
-                if let Some(expr) = self.last_item().and_then(|item| item.to_expr()) {
-                    if let ast::ExprKind::MethodCall(..) = expr.node {
+                if let Some(ref expr) = self.last_item().and_then(|item| item.to_expr()) {
+                    if is_method_call(expr) {
                         self.context.force_one_line_chain.replace(true);
                     }
                 }
@@ -279,13 +268,14 @@ fn try_overflow_last_item(&self, list_items: &mut Vec<ListItem>) -> DefinitiveLi
                 if self.items.len() == 1 =>
             {
                 // When we are rewriting a nested function call, we restrict the
-                // bugdet for the inner function to avoid them being deeply nested.
+                // budget for the inner function to avoid them being deeply nested.
                 // However, when the inner function has a prefix or a suffix
                 // (e.g. `foo() as u32`), this budget reduction may produce poorly
                 // formatted code, where a prefix or a suffix being left on its own
                 // line. Here we explicitlly check those cases.
                 if count_newlines(overflowed) == 1 {
-                    let rw = self.items
+                    let rw = self
+                        .items
                         .last()
                         .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape));
                     let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n'));
@@ -302,14 +292,17 @@ fn try_overflow_last_item(&self, list_items: &mut Vec<ListItem>) -> DefinitiveLi
                 list_items[self.items.len() - 1].item = placeholder;
             }
             _ if self.items.len() >= 1 => {
-                list_items[self.items.len() - 1].item = self.items
+                list_items[self.items.len() - 1].item = self
+                    .items
                     .last()
                     .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape));
 
                 // Use horizontal layout for a function with a single argument as long as
                 // everything fits in a single line.
                 // `self.one_line_width == 0` means vertical layout is forced.
-                if self.items.len() == 1 && self.one_line_width != 0 && !list_items[0].has_comment()
+                if self.items.len() == 1
+                    && self.one_line_width != 0
+                    && !list_items[0].has_comment()
                     && !list_items[0].inner_as_ref().contains('\n')
                     && ::lists::total_item_width(&list_items[0]) <= self.one_line_width
                 {
@@ -404,10 +397,7 @@ fn rewrite_items(&self) -> Option<(bool, String)> {
 
     fn wrap_items(&self, items_str: &str, shape: Shape, is_extendable: bool) -> String {
         let shape = Shape {
-            width: shape
-                .width
-                .checked_sub(last_line_width(self.ident))
-                .unwrap_or(0),
+            width: shape.width.saturating_sub(last_line_width(self.ident)),
             ..shape
         };
 
@@ -415,14 +405,16 @@ fn wrap_items(&self, items_str: &str, shape: Shape, is_extendable: bool) -> Stri
             Some((lhs, rhs)) => (lhs, rhs),
             _ => (self.prefix, self.suffix),
         };
-        let paren_overhead = paren_overhead(self.context);
-        let fits_one_line = items_str.len() + paren_overhead <= shape.width;
+
+        // 2 = `()`
+        let fits_one_line = items_str.len() + 2 <= shape.width;
         let extend_width = if items_str.is_empty() {
-            paren_overhead
+            2
         } else {
-            paren_overhead / 2
+            first_line_width(items_str) + 1
         };
-        let nested_indent_str = self.nested_shape
+        let nested_indent_str = self
+            .nested_shape
             .indent
             .to_string_with_newline(self.context.config);
         let indent_str = shape
@@ -438,13 +430,7 @@ fn wrap_items(&self, items_str: &str, shape: Shape, is_extendable: bool) -> Stri
             || (self.context.inside_macro() && !items_str.contains('\n') && fits_one_line)
             || (is_extendable && extend_width <= shape.width)
         {
-            if self.context.config.spaces_within_parens_and_brackets() && !items_str.is_empty() {
-                result.push(' ');
-                result.push_str(items_str);
-                result.push(' ');
-            } else {
-                result.push_str(items_str);
-            }
+            result.push_str(items_str);
         } else {
             if !items_str.is_empty() {
                 result.push_str(&nested_indent_str);
@@ -460,7 +446,8 @@ fn rewrite(&self, shape: Shape) -> Option<String> {
         let (extendable, items_str) = self.rewrite_items()?;
 
         // If we are using visual indent style and failed to format, retry with block indent.
-        if !self.context.use_block_indent() && need_block_indent(&items_str, self.nested_shape)
+        if !self.context.use_block_indent()
+            && need_block_indent(&items_str, self.nested_shape)
             && !extendable
         {
             self.context.use_block.replace(true);