{
option.suppress_comma();
option.snuggle();
- option.compress_where();
+ option.allow_single_line();
}
let misssing_span = mk_sp(self_ty.span.hi(), item.span.hi());
where_span_end,
self_ty.span.hi(),
option,
- false,
)?;
// If there is no where-clause, we may have missing comments between the trait name and
None,
pos_before_where,
option,
- false,
)?;
// If the where-clause cannot fit on the same line,
// put the where-clause on a new line
result.push_str(&generics_str);
let where_budget = context.budget(last_line_width(&result));
- let option = WhereClauseOption::new(true, false);
+ let option = WhereClauseOption::new(true, WhereClauseSpace::Newline);
rewrite_where_clause(
context,
&generics.where_clause,
None,
body_hi,
option,
- false,
)?
}
None => "".to_owned(),
None,
generics.span.hi(),
option,
- false,
)?;
result.push_str(&where_clause_str);
let is_args_multi_lined = arg_str.contains('\n');
- let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty());
+ let space = if put_args_in_block && ret_str.is_empty() {
+ WhereClauseSpace::Space
+ } else {
+ WhereClauseSpace::Newline
+ };
+ let mut option = WhereClauseOption::new(!has_body, space);
+ if is_args_multi_lined {
+ option.veto_single_line();
+ }
let where_clause_str = rewrite_where_clause(
context,
where_clause,
Some(span.hi()),
pos_before_where,
option,
- is_args_multi_lined,
)?;
// If there are neither where-clause nor return type, we may be missing comments between
// args and `{`.
Some((result, force_new_line_for_brace))
}
+/// Kind of spaces to put before `where`.
+#[derive(Copy, Clone)]
+enum WhereClauseSpace {
+ /// A single space.
+ Space,
+ /// A new line.
+ Newline,
+ /// Nothing.
+ None,
+}
+
#[derive(Copy, Clone)]
struct WhereClauseOption {
suppress_comma: bool, // Force no trailing comma
- snuggle: bool, // Do not insert newline before `where`
- compress_where: bool, // Try single line where-clause instead of vertical layout
+ snuggle: WhereClauseSpace,
+ allow_single_line: bool, // Try single line where-clause instead of vertical layout
+ veto_single_line: bool, // Disallow a single-line where-clause.
}
impl WhereClauseOption {
- fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption {
+ fn new(suppress_comma: bool, snuggle: WhereClauseSpace) -> WhereClauseOption {
WhereClauseOption {
suppress_comma,
snuggle,
- compress_where: false,
+ allow_single_line: false,
+ veto_single_line: false,
}
}
fn snuggled(current: &str) -> WhereClauseOption {
WhereClauseOption {
suppress_comma: false,
- snuggle: last_line_width(current) == 1,
- compress_where: false,
+ snuggle: if last_line_width(current) == 1 {
+ WhereClauseSpace::Space
+ } else {
+ WhereClauseSpace::Newline
+ },
+ allow_single_line: false,
+ veto_single_line: false,
}
}
self.suppress_comma = true
}
- fn compress_where(&mut self) {
- self.compress_where = true
+ fn allow_single_line(&mut self) {
+ self.allow_single_line = true
}
fn snuggle(&mut self) {
- self.snuggle = true
+ self.snuggle = WhereClauseSpace::Space
+ }
+
+ fn veto_single_line(&mut self) {
+ self.veto_single_line = true;
}
}
span_end: Option<BytePos>,
span_end_before_where: BytePos,
where_clause_option: WhereClauseOption,
- is_args_multi_line: bool,
) -> Option<String> {
+ let (where_keyword, allow_single_line) = rewrite_where_keyword(
+ context,
+ where_clause,
+ shape,
+ span_end_before_where,
+ where_clause_option,
+ )?;
+
+ // 1 = `,`
+ let clause_shape = shape
+ .block()
+ .with_max_width(context.config)
+ .block_left(context.config.tab_spaces())?
+ .sub_width(1)?;
+ let force_single_line = context.config.where_single_line()
+ && where_clause.predicates.len() == 1
+ && !where_clause_option.veto_single_line;
+
+ let preds_str = rewrite_bounds_on_where_clause(
+ context,
+ where_clause,
+ clause_shape,
+ terminator,
+ span_end,
+ where_clause_option,
+ force_single_line,
+ )?;
+
+ // 6 = `where `
+ let clause_sep =
+ if allow_single_line && !preds_str.contains('\n') && 6 + preds_str.len() <= shape.width
+ || force_single_line
+ {
+ Cow::from(" ")
+ } else {
+ clause_shape.indent.to_string_with_newline(context.config)
+ };
+
+ Some(format!("{}{}{}", where_keyword, clause_sep, preds_str))
+}
+
+/// Rewrite `where` and comment around it.
+fn rewrite_where_keyword(
+ context: &RewriteContext<'_>,
+ where_clause: &ast::WhereClause,
+ shape: Shape,
+ span_end_before_where: BytePos,
+ where_clause_option: WhereClauseOption,
+) -> Option<(String, bool)> {
let block_shape = shape.block().with_max_width(context.config);
+ // 1 = `,`
+ let clause_shape = block_shape
+ .block_left(context.config.tab_spaces())?
+ .sub_width(1)?;
+
+ let comment_separator = |comment: &str, shape: Shape| {
+ if comment.is_empty() {
+ Cow::from("")
+ } else {
+ shape.indent.to_string_with_newline(context.config)
+ }
+ };
let (span_before, span_after) =
missing_span_before_after_where(span_end_before_where, where_clause);
let (comment_before, comment_after) =
rewrite_comments_before_after_where(context, span_before, span_after, shape)?;
- let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() {
- Cow::from(" ")
- } else {
- block_shape.indent.to_string_with_newline(context.config)
+ let starting_newline = match where_clause_option.snuggle {
+ WhereClauseSpace::Space if comment_before.is_empty() => Cow::from(" "),
+ WhereClauseSpace::None => Cow::from(""),
+ _ => block_shape.indent.to_string_with_newline(context.config),
};
- let clause_shape = block_shape.block_left(context.config.tab_spaces())?;
- // 1 = `,`
- let clause_shape = clause_shape.sub_width(1)?;
- // each clause on one line, trailing comma (except if suppress_comma)
+ let newline_before_where = comment_separator(&comment_before, shape);
+ let newline_after_where = comment_separator(&comment_after, clause_shape);
+ let result = format!(
+ "{}{}{}where{}{}",
+ starting_newline, comment_before, newline_before_where, newline_after_where, comment_after
+ );
+ let allow_single_line = where_clause_option.allow_single_line
+ && comment_before.is_empty()
+ && comment_after.is_empty();
+
+ Some((result, allow_single_line))
+}
+
+/// Rewrite bounds on a where clause.
+fn rewrite_bounds_on_where_clause(
+ context: &RewriteContext<'_>,
+ where_clause: &ast::WhereClause,
+ shape: Shape,
+ terminator: &str,
+ span_end: Option<BytePos>,
+ where_clause_option: WhereClauseOption,
+ force_single_line: bool,
+) -> Option<String> {
let span_start = where_clause.predicates[0].span().lo();
// If we don't have the start of the next span, then use the end of the
// predicates, but that means we miss comments.
",",
|pred| pred.span().lo(),
|pred| pred.span().hi(),
- |pred| pred.rewrite(context, clause_shape),
+ |pred| pred.rewrite(context, shape),
span_start,
span_end,
false,
);
- let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line;
- let comma_tactic = if where_clause_option.suppress_comma || where_single_line {
+ let comma_tactic = if where_clause_option.suppress_comma || force_single_line {
SeparatorTactic::Never
} else {
context.config.trailing_comma()
};
- // shape should be vertical only and only if we have `where_single_line` option enabled
+ // shape should be vertical only and only if we have `force_single_line` option enabled
// and the number of items of the where-clause is equal to 1
- let shape_tactic = if where_single_line {
+ let shape_tactic = if force_single_line {
DefinitiveListTactic::Horizontal
} else {
DefinitiveListTactic::Vertical
};
- let fmt = ListFormatting::new(clause_shape, context.config)
+ let fmt = ListFormatting::new(shape, context.config)
.tactic(shape_tactic)
.trailing_separator(comma_tactic)
.preserve_newline(true);
- let preds_str = write_list(&items.collect::<Vec<_>>(), &fmt)?;
-
- let comment_separator = |comment: &str, shape: Shape| {
- if comment.is_empty() {
- Cow::from("")
- } else {
- shape.indent.to_string_with_newline(context.config)
- }
- };
- let newline_before_where = comment_separator(&comment_before, shape);
- let newline_after_where = comment_separator(&comment_after, clause_shape);
-
- // 6 = `where `
- let clause_sep = if where_clause_option.compress_where
- && comment_before.is_empty()
- && comment_after.is_empty()
- && !preds_str.contains('\n')
- && 6 + preds_str.len() <= shape.width
- || where_single_line
- {
- Cow::from(" ")
- } else {
- clause_shape.indent.to_string_with_newline(context.config)
- };
- Some(format!(
- "{}{}{}where{}{}{}{}",
- starting_newline,
- comment_before,
- newline_before_where,
- newline_after_where,
- comment_after,
- clause_sep,
- preds_str
- ))
+ write_list(&items.collect::<Vec<_>>(), &fmt)
}
fn rewrite_where_clause(
span_end: Option<BytePos>,
span_end_before_where: BytePos,
where_clause_option: WhereClauseOption,
- is_args_multi_line: bool,
) -> Option<String> {
if where_clause.predicates.is_empty() {
return Some(String::new());
span_end,
span_end_before_where,
where_clause_option,
- is_args_multi_line,
);
}
Some(span.hi()),
span_end_before_where,
option,
- false,
)?;
result.push_str(&where_clause_str);
(