diff --git a/src/expr.rs b/src/expr.rs index 7953c344b40..e49d8a99ad5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -25,7 +25,7 @@ use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle, Style}; use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, - ListItem, ListTactic, Separator, SeparatorTactic}; + ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; use patterns::{can_be_overflowed_pat, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; @@ -473,6 +473,7 @@ where } else { SeparatorTactic::Vertical }, + separator_place: SeparatorPlace::Back, shape: nested_shape, ends_with_newline: ends_with_newline, preserve_newline: false, @@ -555,6 +556,7 @@ fn rewrite_closure_fn_decl( tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, shape: arg_shape, ends_with_newline: false, preserve_newline: true, @@ -1578,6 +1580,7 @@ fn rewrite_match_arms( // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. separator: "", trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, shape: arm_shape, ends_with_newline: true, preserve_newline: true, @@ -1659,6 +1662,7 @@ fn rewrite_match_pattern( tactic: tactic, separator: " |", trailing_separator: SeparatorTactic::Never, + separator_place: context.config.match_pattern_separator_break_point(), shape: pat_shape, ends_with_newline: false, preserve_newline: false, @@ -2161,6 +2165,7 @@ where } else { context.config.trailing_comma() }, + separator_place: SeparatorPlace::Back, shape: shape, ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical, preserve_newline: false, @@ -2761,6 +2766,7 @@ where tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, shape: shape, ends_with_newline: false, preserve_newline: false, diff --git a/src/imports.rs b/src/imports.rs index f42975ff919..e5dfb12f4c4 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -17,7 +17,7 @@ use Shape; use codemap::SpanUtils; use config::IndentStyle; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, - ListItem, Separator, SeparatorTactic}; + ListItem, Separator, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::{rewrite_path, PathContext}; use utils; @@ -496,6 +496,7 @@ fn rewrite_use_list( } else { SeparatorTactic::Never }, + separator_place: SeparatorPlace::Back, shape: nested_shape, ends_with_newline: ends_with_newline, preserve_newline: true, diff --git a/src/items.rs b/src/items.rs index 302d15ee8aa..99b189d341c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -24,7 +24,7 @@ use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent, Style}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_call_inner, ExprType}; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, - ListItem, ListTactic, Separator, SeparatorTactic}; + ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::join_bounds; use utils::{colon_spaces, contains_skip, end_typaram, first_line_width, format_abi, @@ -481,6 +481,7 @@ impl<'a> FmtVisitor<'a> { tactic: DefinitiveListTactic::Vertical, separator: ",", trailing_separator: self.config.trailing_comma(), + separator_place: SeparatorPlace::Back, shape: shape, ends_with_newline: true, preserve_newline: true, @@ -2267,6 +2268,7 @@ fn rewrite_args( } else { trailing_comma }, + separator_place: SeparatorPlace::Back, shape: Shape::legacy(budget, indent), ends_with_newline: tactic.ends_with_newline(context.config.fn_args_layout()), preserve_newline: true, @@ -2462,6 +2464,7 @@ where } else { context.config.trailing_comma() }, + separator_place: SeparatorPlace::Back, shape: shape, ends_with_newline: tactic.ends_with_newline(context.config.generics_indent()), preserve_newline: true, @@ -2574,6 +2577,7 @@ fn rewrite_where_clause_rfc_style( tactic: DefinitiveListTactic::Vertical, separator: ",", trailing_separator: comma_tactic, + separator_place: SeparatorPlace::Back, shape: clause_shape, ends_with_newline: true, preserve_newline: true, @@ -2685,6 +2689,7 @@ fn rewrite_where_clause( tactic: tactic, separator: ",", trailing_separator: comma_tactic, + separator_place: SeparatorPlace::Back, shape: Shape::legacy(budget, offset), ends_with_newline: tactic.ends_with_newline(context.config.where_pred_indent()), preserve_newline: true, diff --git a/src/lists.rs b/src/lists.rs index 3fd9b1ab93c..ea34cdfc480 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -61,6 +61,7 @@ pub struct ListFormatting<'a> { pub tactic: DefinitiveListTactic, pub separator: &'a str, pub trailing_separator: SeparatorTactic, + pub separator_place: SeparatorPlace, pub shape: Shape, // Non-expressions, e.g. items, will have a new line at the end of the list. // Important for comment styles. @@ -70,6 +71,19 @@ pub struct ListFormatting<'a> { pub config: &'a Config, } +impl<'a> ListFormatting<'a> { + pub fn needs_trailing_separator(&self) -> bool { + match self.trailing_separator { + // We always put separator in front. + SeparatorTactic::Always => true, + SeparatorTactic::Vertical => self.tactic == DefinitiveListTactic::Vertical, + SeparatorTactic::Never => { + self.tactic == DefinitiveListTactic::Vertical && self.separator_place.is_front() + } + } + } +} + impl AsRef for ListItem { fn as_ref(&self) -> &ListItem { self @@ -165,6 +179,32 @@ impl Separator { } } +/// Where to put separator. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum SeparatorPlace { + Front, + Back, +} + +impl_enum_serialize_and_deserialize!(SeparatorPlace, Front, Back); + +impl SeparatorPlace { + pub fn is_front(&self) -> bool { + *self == SeparatorPlace::Front + } + + pub fn is_back(&self) -> bool { + *self == SeparatorPlace::Back + } + + pub fn from_tactic(default: SeparatorPlace, tactic: DefinitiveListTactic) -> SeparatorPlace { + match tactic { + DefinitiveListTactic::Vertical => default, + _ => SeparatorPlace::Back, + } + } +} + pub fn definitive_tactic( items: I, tactic: ListTactic, @@ -214,11 +254,12 @@ where // Now that we know how we will layout, we can decide for sure if there // will be a trailing separator. - let mut trailing_separator = needs_trailing_separator(formatting.trailing_separator, tactic); + let mut trailing_separator = formatting.needs_trailing_separator(); let mut result = String::new(); let cloned_items = items.clone(); let mut iter = items.into_iter().enumerate().peekable(); let mut item_max_width: Option = None; + let mut sep_place = SeparatorPlace::from_tactic(formatting.separator_place, tactic); let mut line_len = 0; let indent_str = &formatting.shape.indent.to_string(formatting.config); @@ -258,13 +299,16 @@ where result.push('\n'); result.push_str(indent_str); line_len = 0; - if tactic == DefinitiveListTactic::Mixed && formatting.ends_with_newline { + if formatting.ends_with_newline { if last { separate = true; } else { trailing_separator = true; } } + sep_place = formatting.separator_place; + } else { + sep_place = SeparatorPlace::Back; } if line_len > 0 { @@ -314,6 +358,10 @@ where item_max_width = None; } + if separate && sep_place.is_front() && !first { + result.push_str(formatting.separator.trim()); + result.push(' '); + } result.push_str(&inner_item[..]); // Post-comments @@ -330,7 +378,7 @@ where result.push_str(&formatted_comment); } - if separate { + if separate && sep_place.is_back() { result.push_str(formatting.separator); } @@ -642,17 +690,6 @@ where } } -fn needs_trailing_separator( - separator_tactic: SeparatorTactic, - list_tactic: DefinitiveListTactic, -) -> bool { - match separator_tactic { - SeparatorTactic::Always => true, - SeparatorTactic::Vertical => list_tactic == DefinitiveListTactic::Vertical, - SeparatorTactic::Never => false, - } -} - /// Returns the count and total width of the list items. fn calculate_width(items: I) -> (usize, usize) where @@ -762,6 +799,7 @@ pub fn struct_lit_formatting<'a>( } else { context.config.trailing_comma() }, + separator_place: SeparatorPlace::Back, shape: shape, ends_with_newline: ends_with_newline, preserve_newline: true, diff --git a/src/types.rs b/src/types.rs index 61ef03b1687..455c4ad5ae4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -23,7 +23,7 @@ use config::{IndentStyle, Style, TypeDensity}; use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens}; use items::{format_generics_item_list, generics_shape_from_config}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, - SeparatorTactic}; + SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use utils::{colon_spaces, extra_offset, format_mutability, last_line_width, mk_sp, wrap_str}; @@ -365,6 +365,7 @@ where } else { context.config.trailing_comma() }, + separator_place: SeparatorPlace::Back, shape: list_shape, ends_with_newline: tactic.ends_with_newline(context.config.fn_call_style()), preserve_newline: true, diff --git a/src/vertical.rs b/src/vertical.rs index 1a62cad7757..5c48acbb9d0 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -20,7 +20,8 @@ use codemap::SpanUtils; use comment::{combine_strs_with_missing_comments, contains_comment}; use expr::rewrite_field; use items::{rewrite_struct_field, rewrite_struct_field_prefix}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, + SeparatorPlace}; use rewrite::{Rewrite, RewriteContext}; use utils::{contains_skip, is_attributes_extendable, mk_sp}; @@ -257,6 +258,7 @@ fn rewrite_aligned_items_inner( tactic: tactic, separator: ",", trailing_separator: context.config.trailing_comma(), + separator_place: SeparatorPlace::Back, shape: item_shape, ends_with_newline: true, preserve_newline: true, diff --git a/src/visitor.rs b/src/visitor.rs index c5d91fee5b3..5777a871d05 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -24,7 +24,8 @@ use config::{BraceStyle, Config}; use expr::{format_expr, ExprType}; use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_associated_type, rewrite_static, rewrite_type_alias}; -use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorTactic}; +use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, + SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; use regex::Regex; use rewrite::{Rewrite, RewriteContext}; @@ -917,6 +918,7 @@ impl Rewrite for ast::MetaItem { tactic: DefinitiveListTactic::Mixed, separator: ",", trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, shape: item_shape, ends_with_newline: false, preserve_newline: false,