// Formatting top-level items - functions, structs, enums, traits, impls.
-use Indent;
+use {Indent, Shape};
use codemap::SpanUtils;
use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str,
- last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr};
-use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic,
+ last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr,
+ trimmed_last_line_width};
+use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, list_helper,
DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list};
use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annotation_separator};
use comment::{FindUncommented, contains_comment};
use visitor::FmtVisitor;
use rewrite::{Rewrite, RewriteContext};
-use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, FnArgLayoutStyle};
+use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, FnArgLayoutStyle, Style};
use itertools::Itertools;
use syntax::{ast, abi, codemap, ptr, symbol};
// Statements of the form
// let pat: ty = init;
impl Rewrite for ast::Local {
- fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
+ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
+ debug!("Local::rewrite {:?} {} {:?}",
+ self,
+ shape.width,
+ shape.indent);
let mut result = "let ".to_owned();
- let pattern_offset = offset + result.len();
+ let pattern_offset = shape.indent + result.len();
// 1 = ;
- let pattern_width = try_opt!(width.checked_sub(pattern_offset.width() + 1));
+ let pattern_width = try_opt!(shape.width.checked_sub(pattern_offset.width() + 1));
- let pat_str = try_opt!(self.pat.rewrite(&context, pattern_width, pattern_offset));
+ let pat_str = try_opt!(self.pat.rewrite(&context,
+ Shape::legacy(pattern_width, pattern_offset)));
result.push_str(&pat_str);
// String that is placed within the assignment pattern and expression.
if let Some(ref ty) = self.ty {
let separator = type_annotation_separator(context.config);
- let indent = offset + last_line_width(&result) + separator.len();
+ let indent = shape.indent + last_line_width(&result) + separator.len();
// 1 = ;
- let budget = try_opt!(width.checked_sub(indent.width() + 1));
- let rewrite = try_opt!(ty.rewrite(context, budget, indent));
+ let budget = try_opt!(shape.width.checked_sub(indent.width() + 1));
+ let rewrite = try_opt!(ty.rewrite(context, Shape::legacy(budget, indent)));
infix.push_str(separator);
infix.push_str(&rewrite);
result.push_str(&infix);
if let Some(ref ex) = self.init {
- let budget = try_opt!(width.checked_sub(context.block_indent.width() + 1));
-
// 1 = trailing semicolon;
- result =
- try_opt!(rewrite_assign_rhs(&context, result, ex, budget, context.block_indent));
+ let budget = try_opt!(shape.width.checked_sub(shape.indent.block_only().width() + 1));
+
+ result = try_opt!(rewrite_assign_rhs(&context,
+ result,
+ ex,
+ Shape::legacy(budget, shape.indent.block_only())));
}
result.push(';');
}
}
+// TODO convert to using rewrite style rather than visitor
+// TODO format modules in this style
+#[allow(dead_code)]
+struct Item<'a> {
+ keyword: &'static str,
+ abi: String,
+ vis: Option<&'a ast::Visibility>,
+ body: Vec<BodyElement<'a>>,
+ span: Span,
+}
+
+impl<'a> Item<'a> {
+ fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> {
+ let abi = if fm.abi == abi::Abi::C && !config.force_explicit_abi {
+ "extern".into()
+ } else {
+ format!("extern {}", fm.abi)
+ };
+ Item {
+ keyword: "",
+ abi: abi,
+ vis: None,
+ body: fm.items
+ .iter()
+ .map(|i| BodyElement::ForeignItem(i))
+ .collect(),
+ span: span,
+ }
+ }
+}
+
+enum BodyElement<'a> {
+ // Stmt(&'a ast::Stmt),
+ // Field(&'a ast::Field),
+ // Variant(&'a ast::Variant),
+ // Item(&'a ast::Item),
+ ForeignItem(&'a ast::ForeignItem),
+}
+
impl<'a> FmtVisitor<'a> {
- pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) {
- let abi_str = ::utils::format_abi(fm.abi, self.config.force_explicit_abi);
- self.buffer.push_str(&abi_str);
+ fn format_item(&mut self, item: Item) {
+ self.buffer.push_str(&item.abi);
+ self.buffer.push_str(" ");
- let snippet = self.snippet(span);
+ let snippet = self.snippet(item.span);
let brace_pos = snippet.find_uncommented("{").unwrap();
self.buffer.push_str("{");
- if !fm.items.is_empty() || contains_comment(&snippet[brace_pos..]) {
+ if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) {
// FIXME: this skips comments between the extern keyword and the opening
// brace.
- self.last_pos = span.lo + BytePos(brace_pos as u32 + 1);
+ self.last_pos = item.span.lo + BytePos(brace_pos as u32 + 1);
self.block_indent = self.block_indent.block_indent(self.config);
- if fm.items.is_empty() {
- self.format_missing_no_indent(span.hi - BytePos(1));
+ if item.body.is_empty() {
+ self.format_missing_no_indent(item.span.hi - BytePos(1));
self.block_indent = self.block_indent.block_unindent(self.config);
self.buffer.push_str(&self.block_indent.to_string(self.config));
} else {
- for item in &fm.items {
- self.format_foreign_item(&*item);
+ for item in &item.body {
+ self.format_body_element(item);
}
self.block_indent = self.block_indent.block_unindent(self.config);
- self.format_missing_with_indent(span.hi - BytePos(1));
+ self.format_missing_with_indent(item.span.hi - BytePos(1));
}
}
self.buffer.push_str("}");
- self.last_pos = span.hi;
+ self.last_pos = item.span.hi;
+ }
+
+ fn format_body_element(&mut self, element: &BodyElement) {
+ match *element {
+ BodyElement::ForeignItem(ref item) => self.format_foreign_item(item),
+ }
+ }
+
+ pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) {
+ let item = Item::from_foreign_mod(fm, span, self.config);
+ self.format_item(item);
}
fn format_foreign_item(&mut self, item: &ast::ForeignItem) {
&item.vis,
span,
false,
+ false,
false);
match rewrite {
let offset = self.block_indent + prefix.len();
// 1 = ;
let width = self.config.max_width - offset.width() - 1;
- let rewrite = ty.rewrite(&self.get_context(), width, offset);
+ let rewrite = ty.rewrite(&self.get_context(), Shape::legacy(width, offset));
match rewrite {
Some(result) => {
vis,
span,
newline_brace,
- has_body));
+ has_body,
+ true));
if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') {
newline_brace = false;
&ast::Visibility::Inherited,
span,
false,
+ false,
false));
// Re-attach semicolon
let suffix = if semicolon_for_expr(e) { ";" } else { "" };
e.rewrite(&self.get_context(),
- self.config.max_width - self.block_indent.width(),
- self.block_indent)
+ Shape::legacy(self.config.max_width -
+ self.block_indent.width(),
+ self.block_indent))
.map(|s| s + suffix)
.or_else(|| Some(self.snippet(e.span)))
}
None => {
stmt.rewrite(&self.get_context(),
- self.config.max_width - self.block_indent.width(),
- self.block_indent)
+ Shape::legacy(self.config.max_width -
+ self.block_indent.width(),
+ self.block_indent))
}
}
} else {
self.block_indent,
self.block_indent.block_indent(self.config),
mk_sp(span.lo, body_start))
- .unwrap();
+ .unwrap();
self.buffer.push_str(&generics_str);
self.last_pos = body_start;
let fmt = ListFormatting {
tactic: DefinitiveListTactic::Vertical,
separator: ",",
- trailing_separator: SeparatorTactic::from_bool(self.config.enum_trailing_comma),
- indent: self.block_indent,
- width: budget,
+ trailing_separator: self.config.trailing_comma,
+ shape: Shape::legacy(budget, self.block_indent),
ends_with_newline: true,
config: self.config,
};
}
let indent = self.block_indent;
- let mut result = try_opt!(field.node
- .attrs
- .rewrite(&self.get_context(),
- self.config.max_width - indent.width(),
- indent));
+ let mut result = try_opt!(field.node.attrs.rewrite(&self.get_context(),
+ Shape::legacy(self.config.max_width -
+ indent.width(),
+ indent)));
if !result.is_empty() {
result.push('\n');
result.push_str(&indent.to_string(self.config));
wrap_str(tag,
self.config.max_width,
- self.config.max_width - indent.width(),
- indent)
+ Shape::legacy(self.config.max_width - indent.width(), indent))
}
};
pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option<String> {
if let ast::ItemKind::Impl(_, _, ref generics, ref trait_ref, _, ref items) = item.node {
let mut result = String::new();
-
// First try to format the ref and type without a split at the 'for'.
let mut ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, false));
// If there is a line break present in the first result format it again
// with a split at the 'for'. Skip this if there is no trait ref and
// therefore no 'for'.
- if let Some(_) = *trait_ref {
- if ref_and_type.contains('\n') {
- ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, true));
- }
+ if ref_and_type.contains('\n') && trait_ref.is_some() {
+ ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, true));
}
result.push_str(&ref_and_type);
let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result)));
let where_clause_str = try_opt!(rewrite_where_clause(context,
&generics.where_clause,
- context.config,
context.config.item_brace_style,
- context.block_indent,
- where_budget,
+ Shape::legacy(where_budget,
+ offset.block_only()),
context.config.where_density,
"{",
- true,
+ false,
+ last_line_width(&ref_and_type) == 1,
None));
if try_opt!(is_impl_single_line(context, &items, &result, &where_clause_str, &item)) {
if !where_clause_str.is_empty() && !where_clause_str.contains('\n') {
result.push('\n');
- let width = context.block_indent.width() + context.config.tab_spaces - 1;
+ let width = offset.block_indent + context.config.tab_spaces - 1;
let where_indent = Indent::new(0, width);
result.push_str(&where_indent.to_string(context.config));
}
if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config);
- visitor.block_indent = context.block_indent.block_indent(context.config);
+ visitor.block_indent = offset.block_only().block_indent(context.config);
visitor.last_pos = item.span.lo + BytePos(open_pos as u32);
for item in items {
visitor.format_missing(item.span.hi - BytePos(1));
let inner_indent_str = visitor.block_indent.to_string(context.config);
- let outer_indent_str = context.block_indent.to_string(context.config);
+ let outer_indent_str = offset.block_only().to_string(context.config);
result.push('\n');
result.push_str(&inner_indent_str);
item.node {
let mut result = String::new();
- result.push_str(&*format_visibility(&item.vis));
+ result.push_str(&format_visibility(&item.vis));
result.push_str(format_unsafety(unsafety));
result.push_str("impl");
};
let generics_str = try_opt!(rewrite_generics(context,
generics,
- offset,
- context.config.max_width,
+ Shape::legacy(context.config.max_width,
+ offset),
offset + result.len(),
mk_sp(lo, hi)));
result.push_str(&generics_str);
- result.push(' ');
if polarity == ast::ImplPolarity::Negative {
- result.push('!');
+ result.push_str(" !");
}
if let Some(ref trait_ref) = *trait_ref {
- let budget = try_opt!(context.config.max_width.checked_sub(result.len()));
- let indent = offset + result.len();
- result.push_str(&*try_opt!(trait_ref.rewrite(context, budget, indent)));
+ if polarity != ast::ImplPolarity::Negative {
+ result.push_str(" ");
+ }
+ let used_space = last_line_width(&result);
+ let budget = try_opt!(context.config.max_width.checked_sub(used_space));
+ let indent = offset + used_space;
+ result.push_str(&*try_opt!(trait_ref.rewrite(context, Shape::legacy(budget, indent))));
if split_at_for {
result.push('\n');
// Add indentation of one additional tab.
- let width = context.block_indent.width() + context.config.tab_spaces;
+ let width = offset.block_indent + context.config.tab_spaces;
let for_indent = Indent::new(0, width);
result.push_str(&for_indent.to_string(context.config));
- result.push_str("for ");
+ result.push_str("for");
} else {
- result.push_str(" for ");
+ result.push_str(" for");
}
}
}
}
- let budget = try_opt!(context.config.max_width.checked_sub(used_space));
- let indent = offset + result.len();
- result.push_str(&*try_opt!(self_ty.rewrite(context, budget, indent)));
+ // 1 = space before the type.
+ let budget = try_opt!(context.config.max_width.checked_sub(used_space + 1));
+ let indent = offset + result.len() + 1;
+ let self_ty_str = self_ty.rewrite(context, Shape::legacy(budget, indent));
+ if let Some(self_ty_str) = self_ty_str {
+ result.push_str(" ");
+ result.push_str(&self_ty_str);
+ return Some(result);
+ }
+ // Can't fit the self type on what's left of the line, so start a new one.
+ let indent = offset.block_indent(context.config);
+ result.push_str(&format!("\n{}", indent.to_string(context.config)));
+ let budget = try_opt!(context.config.max_width.checked_sub(indent.width()));
+ result.push_str(&*try_opt!(self_ty.rewrite(context, Shape::legacy(budget, indent))));
Some(result)
} else {
unreachable!();
let generics_str = try_opt!(rewrite_generics(context,
generics,
- offset,
- context.config.max_width,
+ Shape::legacy(context.config.max_width,
+ offset),
offset + result.len(),
mk_sp(item.span.lo, body_lo)));
result.push_str(&generics_str);
- let trait_bound_str = try_opt!(rewrite_trait_bounds(context,
- type_param_bounds,
- offset,
- context.config.max_width));
+ let trait_bound_str =
+ try_opt!(rewrite_trait_bounds(context,
+ type_param_bounds,
+ Shape::legacy(context.config.max_width, offset)));
// If the trait, generics, and trait bound cannot fit on the same line,
// put the trait bounds on an indented new line
if offset.width() + last_line_width(&result) + trait_bound_str.len() >
- context.config.ideal_width {
+ context.config.comment_width {
result.push('\n');
- let trait_indent = context.block_indent.block_indent(context.config);
+ let trait_indent = offset.block_only().block_indent(context.config);
result.push_str(&trait_indent.to_string(context.config));
}
result.push_str(&trait_bound_str);
Density::Tall
};
- let where_budget = try_opt!(context.config
- .max_width
- .checked_sub(last_line_width(&result)));
+ let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result)));
let where_clause_str = try_opt!(rewrite_where_clause(context,
&generics.where_clause,
- context.config,
context.config.item_brace_style,
- context.block_indent,
- where_budget,
+ Shape::legacy(where_budget,
+ offset.block_only()),
where_density,
"{",
- has_body,
+ !has_body,
+ trait_bound_str.is_empty() &&
+ last_line_width(&generics_str) == 1,
None));
// If the where clause cannot fit on the same line,
// put the where clause on a new line
if !where_clause_str.contains('\n') &&
last_line_width(&result) + where_clause_str.len() + offset.width() >
- context.config.ideal_width {
+ context.config.comment_width {
result.push('\n');
- let width = context.block_indent.width() + context.config.tab_spaces - 1;
+ let width = offset.block_indent + context.config.tab_spaces - 1;
let where_indent = Indent::new(0, width);
result.push_str(&where_indent.to_string(context.config));
}
if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) {
let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config);
- visitor.block_indent = context.block_indent.block_indent(context.config);
+ visitor.block_indent = offset.block_only().block_indent(context.config);
visitor.last_pos = item.span.lo + BytePos(open_pos as u32);
for item in trait_items {
visitor.format_missing(item.span.hi - BytePos(1));
let inner_indent_str = visitor.block_indent.to_string(context.config);
- let outer_indent_str = context.block_indent.to_string(context.config);
+ let outer_indent_str = offset.block_only().to_string(context.config);
result.push('\n');
result.push_str(&inner_indent_str);
}
None => {
if context.config.item_brace_style == BraceStyle::AlwaysNextLine && !fields.is_empty() {
- format!("\n{}{{", context.block_indent.to_string(context.config))
+ format!("\n{}{{", offset.block_only().to_string(context.config))
} else {
" {".to_owned()
}
// 1 = ","
let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 1));
- let items = itemize_list(context.codemap,
- fields.iter(),
- "}",
- |field| {
- // Include attributes and doc comments, if present
- if !field.attrs.is_empty() {
- field.attrs[0].span.lo
- } else {
- field.span.lo
- }
- },
- |field| field.ty.span.hi,
- |field| field.rewrite(context, item_budget, item_indent),
- context.codemap.span_after(span, "{"),
- span.hi)
- .collect::<Vec<_>>();
+ let items =
+ itemize_list(context.codemap,
+ fields.iter(),
+ "}",
+ |field| {
+ // Include attributes and doc comments, if present
+ if !field.attrs.is_empty() {
+ field.attrs[0].span.lo
+ } else {
+ field.span.lo
+ }
+ },
+ |field| field.ty.span.hi,
+ |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)),
+ context.codemap.span_after(span, "{"),
+ span.hi)
+ .collect::<Vec<_>>();
// 1 = ,
let budget = context.config.max_width - offset.width() + context.config.tab_spaces - 1;
let fmt = ListFormatting {
tactic: tactic,
separator: ",",
- trailing_separator: context.config.struct_trailing_comma,
- indent: item_indent,
- width: budget,
+ trailing_separator: context.config.trailing_comma,
+ shape: Shape::legacy(budget, item_indent),
ends_with_newline: true,
config: context.config,
};
Some(generics) => {
let generics_str = try_opt!(rewrite_generics(context,
generics,
- offset,
- context.config.max_width,
+ Shape::legacy(context.config.max_width,
+ offset),
offset + header_str.len(),
mk_sp(span.lo, body_lo)));
result.push_str(&generics_str);
- let where_budget = try_opt!(context.config
- .max_width
- .checked_sub(last_line_width(&result)));
+ let where_budget =
+ try_opt!(context.config.max_width.checked_sub(last_line_width(&result)));
try_opt!(rewrite_where_clause(context,
&generics.where_clause,
- context.config,
context.config.item_brace_style,
- context.block_indent,
- where_budget,
+ Shape::legacy(where_budget, offset.block_only()),
Density::Compressed,
";",
+ true,
false,
None))
}
None => "".to_owned(),
};
- result.push('(');
-
- let item_indent = context.block_indent + result.len();
- // 2 = ");"
- let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 2));
- let items = itemize_list(context.codemap,
- fields.iter(),
- ")",
- |field| {
- // Include attributes and doc comments, if present
- if !field.attrs.is_empty() {
- field.attrs[0].span.lo
- } else {
- field.span.lo
+ let (tactic, item_indent) = match context.config.fn_args_layout {
+ FnArgLayoutStyle::Visual => {
+ // 1 = `(`
+ (ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1)
+ }
+ FnArgLayoutStyle::Block |
+ FnArgLayoutStyle::BlockAlways => {
+ (ListTactic::HorizontalVertical, offset.block_only().block_indent(&context.config))
+ }
+ };
+ // 3 = `();`
+ let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 3));
+
+ let items =
+ itemize_list(context.codemap,
+ fields.iter(),
+ ")",
+ |field| {
+ // Include attributes and doc comments, if present
+ if !field.attrs.is_empty() {
+ field.attrs[0].span.lo
+ } else {
+ field.span.lo
+ }
+ },
+ |field| field.ty.span.hi,
+ |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)),
+ context.codemap.span_after(span, "("),
+ span.hi);
+ let body_budget = try_opt!(context.config.max_width.checked_sub(offset.block_only().width() +
+ result.len() +
+ 3));
+ let body = try_opt!(list_helper(items,
+ // TODO budget is wrong in block case
+ Shape::legacy(body_budget, item_indent),
+ context.config,
+ tactic));
+
+ if context.config.fn_args_layout == FnArgLayoutStyle::Visual || !body.contains('\n') {
+ result.push('(');
+ if context.config.spaces_within_parens && body.len() > 0 {
+ result.push(' ');
}
- },
- |field| field.ty.span.hi,
- |field| field.rewrite(context, item_budget, item_indent),
- context.codemap.span_after(span, "("),
- span.hi);
- let body = try_opt!(format_item_list(items, item_budget, item_indent, context.config));
-
- if context.config.spaces_within_parens && body.len() > 0 {
- result.push(' ');
- }
- result.push_str(&body);
+ result.push_str(&body);
- if context.config.spaces_within_parens && body.len() > 0 {
- result.push(' ');
+ if context.config.spaces_within_parens && body.len() > 0 {
+ result.push(' ');
+ }
+ result.push(')');
+ } else {
+ result.push_str("(\n");
+ result.push_str(&item_indent.to_string(&context.config));
+ result.push_str(&body);
+ result.push('\n');
+ result.push_str(&offset.block_only().to_string(&context.config));
+ result.push(')');
}
- result.push(')');
-
if !where_clause_str.is_empty() && !where_clause_str.contains('\n') &&
(result.contains('\n') ||
- context.block_indent.width() + result.len() + where_clause_str.len() + 1 >
+ offset.block_indent + result.len() + where_clause_str.len() + 1 >
context.config.max_width) {
- // We need to put the where clause on a new line, but we didn'to_string
+ // We need to put the where clause on a new line, but we didn't
// know that earlier, so the where clause will not be indented properly.
result.push('\n');
- result.push_str(&(context.block_indent + (context.config.tab_spaces - 1))
- .to_string(context.config));
+ result.push_str(&(offset.block_only() + (context.config.tab_spaces - 1))
+ .to_string(context.config));
}
result.push_str(&where_clause_str);
let generics_width = context.config.max_width - " =".len();
let generics_str = try_opt!(rewrite_generics(context,
generics,
- indent,
- generics_width,
+ Shape::legacy(generics_width, indent),
generics_indent,
generics_span));
result.push_str(&generics_str);
- let where_budget = try_opt!(context.config
- .max_width
- .checked_sub(last_line_width(&result)));
+ let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result)));
let where_clause_str = try_opt!(rewrite_where_clause(context,
&generics.where_clause,
- context.config,
context.config.item_brace_style,
- indent,
- where_budget,
+ Shape::legacy(where_budget, indent),
context.config.where_density,
"=",
- false,
+ true,
+ true,
Some(span.hi)));
result.push_str(&where_clause_str);
result.push_str(" = ");
.unwrap_or(0);
let type_indent = indent + line_width;
// Try to fit the type on the same line
- let ty_str = try_opt!(ty.rewrite(context, budget, type_indent)
- .or_else(|| {
- // The line was too short, try to put the type on the next line
+ let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, type_indent)).or_else(|| {
+ // The line was too short, try to put the type on the next line
- // Remove the space after '='
- result.pop();
- let type_indent = indent.block_indent(context.config);
- result.push('\n');
- result.push_str(&type_indent.to_string(context.config));
- let budget = try_opt!(context.config
- .max_width
- .checked_sub(type_indent.width() + ";".len()));
- ty.rewrite(context, budget, type_indent)
- }));
+ // Remove the space after '='
+ result.pop();
+ let type_indent = indent.block_indent(context.config);
+ result.push('\n');
+ result.push_str(&type_indent.to_string(context.config));
+ let budget = try_opt!(context.config.max_width.checked_sub(type_indent.width() +
+ ";".len()));
+ ty.rewrite(context, Shape::legacy(budget, type_indent))
+ }));
result.push_str(&ty_str);
result.push_str(";");
Some(result)
}
impl Rewrite for ast::StructField {
- fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
+ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
if contains_skip(&self.attrs) {
let span = context.snippet(mk_sp(self.attrs[0].span.lo, self.span.hi));
- return wrap_str(span, context.config.max_width, width, offset);
+ return wrap_str(span, context.config.max_width, shape);
}
let name = self.ident;
let vis = format_visibility(&self.vis);
- let mut attr_str = try_opt!(self.attrs
- .rewrite(context, context.config.max_width - offset.width(), offset));
+ let mut attr_str = try_opt!(self.attrs.rewrite(context,
+ Shape::legacy(context.config.max_width -
+ shape.indent.width(),
+ shape.indent)));
if !attr_str.is_empty() {
attr_str.push('\n');
- attr_str.push_str(&offset.to_string(context.config));
+ attr_str.push_str(&shape.indent.to_string(context.config));
}
let type_annotation_spacing = type_annotation_spacing(context.config);
};
let last_line_width = last_line_width(&result);
- let budget = try_opt!(width.checked_sub(last_line_width));
- let rewrite = try_opt!(self.ty.rewrite(context, budget, offset + last_line_width));
+ let budget = try_opt!(shape.width.checked_sub(last_line_width));
+ let rewrite = try_opt!(self.ty.rewrite(context,
+ Shape::legacy(budget,
+ shape.indent + last_line_width)));
Some(result + &rewrite)
}
}
ty: &ast::Ty,
mutability: ast::Mutability,
expr_opt: Option<&ptr::P<ast::Expr>>,
+ offset: Indent,
context: &RewriteContext)
-> Option<String> {
let type_annotation_spacing = type_annotation_spacing(context.config);
type_annotation_spacing.1);
// 2 = " =".len()
let ty_str = try_opt!(ty.rewrite(context,
- context.config.max_width - context.block_indent.width() -
- prefix.len() - 2,
- context.block_indent));
+ Shape::legacy(context.config.max_width - offset.block_indent -
+ prefix.len() -
+ 2,
+ offset.block_only())));
if let Some(expr) = expr_opt {
let lhs = format!("{}{} =", prefix, ty_str);
// 1 = ;
- let remaining_width = context.config.max_width - context.block_indent.width() - 1;
- rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent)
- .map(|s| s + ";")
+ let remaining_width = context.config.max_width - offset.block_indent - 1;
+ rewrite_assign_rhs(context,
+ lhs,
+ expr,
+ Shape::legacy(remaining_width, offset.block_only()))
+ .map(|s| s + ";")
} else {
let lhs = format!("{}{};", prefix, ty_str);
Some(lhs)
let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt {
let bounds: &[_] = ty_param_bounds;
let bound_str = try_opt!(bounds.iter()
- .map(|ty_bound| ty_bound.rewrite(context, context.config.max_width, indent))
+ .map(|ty_bound| {
+ ty_bound.rewrite(context, Shape::legacy(context.config.max_width, indent))
+ })
.intersperse(Some(" + ".to_string()))
.collect::<Option<String>>());
if bounds.len() > 0 {
if let Some(ty) = ty_opt {
let ty_str = try_opt!(ty.rewrite(context,
- context.config.max_width - context.block_indent.width() -
- prefix.len() -
- 2,
- context.block_indent));
+ Shape::legacy(context.config.max_width -
+ indent.block_indent -
+ prefix.len() -
+ 2,
+ indent.block_only())));
Some(format!("{} = {};", prefix, ty_str))
} else {
Some(format!("{}{};", prefix, type_bounds_str))
}
}
+pub fn rewrite_associated_impl_type(ident: ast::Ident,
+ defaultness: ast::Defaultness,
+ ty_opt: Option<&ptr::P<ast::Ty>>,
+ ty_param_bounds_opt: Option<&ast::TyParamBounds>,
+ context: &RewriteContext,
+ indent: Indent)
+ -> Option<String> {
+ let result =
+ try_opt!(rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent));
+
+ match defaultness {
+ ast::Defaultness::Default => Some(format!("default {}", result)),
+ _ => Some(result),
+ }
+}
+
impl Rewrite for ast::FunctionRetTy {
- fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
+ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
match *self {
ast::FunctionRetTy::Default(_) => Some(String::new()),
ast::FunctionRetTy::Ty(ref ty) => {
- let inner_width = try_opt!(width.checked_sub(3));
- ty.rewrite(context, inner_width, offset + 3).map(|r| format!("-> {}", r))
+ let inner_width = try_opt!(shape.width.checked_sub(3));
+ ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)).map(|r| {
+ format!("-> {}", r)
+ })
}
}
}
}
impl Rewrite for ast::Arg {
- fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
+ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
if is_named_arg(self) {
- let mut result = try_opt!(self.pat.rewrite(context, width, offset));
+ let mut result = try_opt!(self.pat.rewrite(context,
+ Shape::legacy(shape.width, shape.indent)));
if self.ty.node != ast::TyKind::Infer {
if context.config.space_before_type_annotation {
if context.config.space_after_type_annotation_colon {
result.push_str(" ");
}
- let max_width = try_opt!(width.checked_sub(result.len()));
- let ty_str = try_opt!(self.ty.rewrite(context, max_width, offset + result.len()));
+ let max_width = try_opt!(shape.width.checked_sub(result.len()));
+ let ty_str = try_opt!(self.ty.rewrite(context,
+ Shape::legacy(max_width,
+ shape.indent + result.len())));
result.push_str(&ty_str);
}
Some(result)
} else {
- self.ty.rewrite(context, width, offset)
+ self.ty.rewrite(context, shape)
}
}
}
let mut_str = format_mutability(m);
match lt {
Some(ref l) => {
- let lifetime_str =
- try_opt!(l.rewrite(context, usize::max_value(), Indent::empty()));
+ let lifetime_str = try_opt!(l.rewrite(context,
+ Shape::legacy(usize::max_value(),
+ Indent::empty())));
Some(format!("&{} {}self", lifetime_str, mut_str))
}
None => Some(format!("&{}self", mut_str)),
assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
let mutability = explicit_self_mutability(&args[0]);
- let type_str = try_opt!(ty.rewrite(context, usize::max_value(), Indent::empty()));
+ let type_str = try_opt!(ty.rewrite(context,
+ Shape::legacy(usize::max_value(), Indent::empty())));
Some(format!("{}self: {}", format_mutability(mutability), type_str))
}
vis: &ast::Visibility,
span: Span,
newline_brace: bool,
- has_body: bool)
+ has_body: bool,
+ has_braces: bool)
-> Option<(String, bool)> {
let mut force_new_line_for_brace = false;
- // FIXME we'll lose any comments in between parts of the function decl, but
- // anyone who comments there probably deserves what they get.
let where_clause = &generics.where_clause;
let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo);
let generics_str = try_opt!(rewrite_generics(context,
generics,
- indent,
- context.config.max_width,
+ Shape::legacy(context.config.max_width, indent),
generics_indent,
generics_span));
result.push_str(&generics_str);
- // Note that if the width and indent really matter, we'll re-layout the
+ let snuggle_angle_bracket = last_line_width(&generics_str) == 1;
+
+ // Note that the width and indent don't really matter, we'll re-layout the
// return type later anyway.
- let ret_str = try_opt!(fd.output
- .rewrite(&context, context.config.max_width - indent.width(), indent));
+ let ret_str = try_opt!(fd.output.rewrite(&context,
+ Shape::legacy(context.config.max_width -
+ indent.width(),
+ indent)));
let multi_line_ret_str = ret_str.contains('\n');
let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() };
multi_line_budget = context.config.max_width - arg_indent.width();
}
- debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
+ debug!("rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
one_line_budget,
multi_line_budget,
arg_indent);
- // Check if vertical layout was forced by compute_budget_for_args.
+ // Check if vertical layout was forced.
if one_line_budget == 0 {
- if context.config.fn_args_paren_newline {
+ if snuggle_angle_bracket {
+ result.push_str("(");
+ } else if context.config.fn_args_paren_newline {
result.push('\n');
result.push_str(&arg_indent.to_string(context.config));
arg_indent = arg_indent + 1; // extra space for `(`
}
// A conservative estimation, to goal is to be over all parens in generics
- let args_start = generics.ty_params
- .last()
- .map_or(span.lo, |tp| end_typaram(tp));
+ let args_start = generics.ty_params.last().map_or(span.lo, |tp| end_typaram(tp));
let args_span = mk_sp(context.codemap.span_after(mk_sp(args_start, span.hi), "("),
span_for_return(&fd.output).lo);
let arg_str = try_opt!(rewrite_args(context,
let multi_line_arg_str = arg_str.contains('\n');
let put_args_in_block = match context.config.fn_args_layout {
- FnArgLayoutStyle::Block => multi_line_arg_str,
+ FnArgLayoutStyle::Block => multi_line_arg_str || generics_str.contains('\n'),
FnArgLayoutStyle::BlockAlways => true,
_ => false,
} && !fd.inputs.is_empty();
Indent::new(indent.width(), result.len())
};
- if multi_line_ret_str {
+ if multi_line_ret_str || ret_should_indent {
// Now that we know the proper indent and width, we need to
// re-layout the return type.
let budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width()));
- let ret_str = try_opt!(fd.output.rewrite(context, budget, ret_indent));
+ let ret_str = try_opt!(fd.output.rewrite(context, Shape::legacy(budget, ret_indent)));
result.push_str(&ret_str);
} else {
result.push_str(&ret_str);
_ => false,
} || (put_args_in_block && ret_str.is_empty());
- let where_density = if should_compress_where {
- Density::Compressed
- } else {
- Density::Tall
- };
+ if where_clause.predicates.len() == 1 && should_compress_where {
+ let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result)));
+ if let Some(where_clause_str) =
+ rewrite_where_clause(context,
+ where_clause,
+ context.config.fn_brace_style,
+ Shape::legacy(budget, indent),
+ Density::Compressed,
+ "{",
+ !has_braces,
+ put_args_in_block && ret_str.is_empty(),
+ Some(span.hi)) {
+ if !where_clause_str.contains('\n') {
+ if last_line_width(&result) + where_clause_str.len() > context.config.max_width {
+ result.push('\n');
+ }
- // Where clause.
- let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result)));
+ result.push_str(&where_clause_str);
+
+ return Some((result, force_new_line_for_brace));
+ }
+ }
+ }
+
+ let budget = try_opt!(context.config.max_width.checked_sub(indent.block_indent));
let where_clause_str = try_opt!(rewrite_where_clause(context,
where_clause,
- context.config,
context.config.fn_brace_style,
- indent,
- where_budget,
- where_density,
+ Shape::legacy(budget, indent),
+ Density::Tall,
"{",
- has_body,
+ !has_braces,
+ put_args_in_block && ret_str.is_empty(),
Some(span.hi)));
- if last_line_width(&result) + where_clause_str.len() > context.config.max_width &&
- !where_clause_str.contains('\n') {
- result.push('\n');
- }
-
result.push_str(&where_clause_str);
Some((result, force_new_line_for_brace))
span: Span,
variadic: bool)
-> Option<String> {
- let mut arg_item_strs = try_opt!(args.iter()
- .map(|arg| arg.rewrite(&context, multi_line_budget, arg_indent))
- .collect::<Option<Vec<_>>>());
+ let mut arg_item_strs =
+ try_opt!(args.iter()
+ .map(|arg| {
+ arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent))
+ })
+ .collect::<Option<Vec<_>>>());
// Account for sugary self.
// FIXME: the comment for the self argument is dropped. This is blocked
}
let variadic_arg = if variadic {
- let variadic_span = mk_sp(args.last().unwrap().ty.span.hi, span.hi);
+ let variadic_span = mk_sp(args.last()
+ .unwrap()
+ .ty
+ .span
+ .hi,
+ span.hi);
let variadic_start = context.codemap.span_after(variadic_span, "...") - BytePos(3);
Some(ArgumentKind::Variadic(variadic_start))
} else {
}
let indent = match context.config.fn_arg_indent {
- BlockIndentStyle::Inherit => indent,
BlockIndentStyle::Tabbed => indent.block_indent(context.config),
BlockIndentStyle::Visual => arg_indent,
};
debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic);
- let end_with_newline = match context.config.fn_args_layout {
- FnArgLayoutStyle::Block |
- FnArgLayoutStyle::BlockAlways => true,
- _ => false,
+ let (trailing_comma, end_with_newline) = match context.config.fn_args_layout {
+ FnArgLayoutStyle::Block => (SeparatorTactic::Vertical, true),
+ FnArgLayoutStyle::BlockAlways => (SeparatorTactic::Always, true),
+ _ => (SeparatorTactic::Never, false),
};
let fmt = ListFormatting {
tactic: tactic,
separator: ",",
- trailing_separator: SeparatorTactic::Never,
- indent: indent,
- width: budget,
+ trailing_separator: trailing_comma,
+ shape: Shape::legacy(budget, indent),
ends_with_newline: end_with_newline,
config: context.config,
};
ret_str_len: usize,
newline_brace: bool)
-> Option<((usize, usize, Indent))> {
+ debug!("compute_budgets_for_args {} {:?}, {}, {}",
+ result.len(),
+ indent,
+ ret_str_len,
+ newline_brace);
// Try keeping everything on the same line.
if !result.contains('\n') {
// 3 = `() `, space is before ret_string.
if !newline_brace {
used_space += 2;
}
- let one_line_budget = context.config.max_width.checked_sub(used_space).unwrap_or(0);
+ let one_line_budget = context.config
+ .max_width
+ .checked_sub(used_space)
+ .unwrap_or(0);
if one_line_budget > 0 {
// 4 = "() {".len()
fn rewrite_generics(context: &RewriteContext,
generics: &ast::Generics,
- offset: Indent,
- width: usize,
+ shape: Shape,
+ // TODO shouldn't need this
generics_offset: Indent,
span: Span)
-> Option<String> {
}
let offset = match context.config.generics_indent {
- BlockIndentStyle::Inherit => offset,
- BlockIndentStyle::Tabbed => offset.block_indent(context.config),
+ BlockIndentStyle::Tabbed => shape.indent.block_indent(context.config),
// 1 = <
BlockIndentStyle::Visual => generics_offset + 1,
};
- let h_budget = try_opt!(width.checked_sub(generics_offset.width() + 2));
+ let h_budget = try_opt!(shape.width.checked_sub(generics_offset.width() + 2));
// FIXME: might need to insert a newline if the generics are really long.
// Strings for the generics.
- let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(context, h_budget, offset));
- let ty_strs = tys.iter().map(|ty_param| ty_param.rewrite(context, h_budget, offset));
+ let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(context, Shape::legacy(h_budget, offset)));
+ let ty_strs =
+ tys.iter().map(|ty_param| ty_param.rewrite(context, Shape::legacy(h_budget, offset)));
// Extract comments between generics.
let lt_spans = lifetimes.iter().map(|l| {
|&(_, ref str)| str.clone(),
context.codemap.span_after(span, "<"),
span.hi);
- let list_str = try_opt!(format_item_list(items, h_budget, offset, context.config));
-
- Some(if context.config.spaces_within_angle_brackets {
+ let list_str =
+ try_opt!(format_item_list(items, Shape::legacy(h_budget, offset), context.config));
+
+ let result = if context.config.generics_indent != BlockIndentStyle::Visual &&
+ list_str.contains('\n') {
+ format!("<\n{}{}\n{}>",
+ offset.to_string(context.config),
+ list_str,
+ shape.indent.to_string(context.config))
+ } else if context.config.spaces_within_angle_brackets {
format!("< {} >", list_str)
} else {
format!("<{}>", list_str)
- })
+ };
+ Some(result)
}
fn rewrite_trait_bounds(context: &RewriteContext,
type_param_bounds: &ast::TyParamBounds,
- indent: Indent,
- width: usize)
+ shape: Shape)
-> Option<String> {
let bounds: &[_] = type_param_bounds;
}
let bound_str = try_opt!(bounds.iter()
- .map(|ty_bound| ty_bound.rewrite(&context, width, indent))
- .intersperse(Some(" + ".to_string()))
- .collect::<Option<String>>());
+ .map(|ty_bound| ty_bound.rewrite(&context, shape))
+ .intersperse(Some(" + ".to_string()))
+ .collect::<Option<String>>());
let mut result = String::new();
result.push_str(": ");
Some(result)
}
+// fn reflow_list_node_with_rule(
+// &self,
+// node: &CompoundNode,
+// rule: &Rule,
+// args: &[Arg],
+// shape: &Shape
+// ) -> Result<String, ()>
+// where
+// T: Foo,
+// {
+
+
+fn rewrite_where_clause_rfc_style(context: &RewriteContext,
+ where_clause: &ast::WhereClause,
+ shape: Shape,
+ terminator: &str,
+ suppress_comma: bool,
+ // where clause can be kept on the current line.
+ snuggle: bool,
+ span_end: Option<BytePos>)
+ -> Option<String> {
+ let block_shape = shape.block();
+
+ let starting_newline = if snuggle {
+ " ".to_owned()
+ } else {
+ "\n".to_owned() + &block_shape.indent.to_string(context.config)
+ };
+
+ let clause_shape = block_shape.block_indent(context.config.tab_spaces);
+ // each clause on one line, trailing comma (except if suppress_comma)
+ let span_start = span_for_where_pred(&where_clause.predicates[0]).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.
+ let len = where_clause.predicates.len();
+ let end_of_preds = span_for_where_pred(&where_clause.predicates[len - 1]).hi;
+ let span_end = span_end.unwrap_or(end_of_preds);
+ let items = itemize_list(context.codemap,
+ where_clause.predicates.iter(),
+ terminator,
+ |pred| span_for_where_pred(pred).lo,
+ |pred| span_for_where_pred(pred).hi,
+ |pred| pred.rewrite(context, clause_shape),
+ span_start,
+ span_end);
+ let comma_tactic = if suppress_comma {
+ SeparatorTactic::Never
+ } else {
+ SeparatorTactic::Always
+ };
+
+ let fmt = ListFormatting {
+ tactic: DefinitiveListTactic::Vertical,
+ separator: ",",
+ trailing_separator: comma_tactic,
+ shape: clause_shape,
+ ends_with_newline: true,
+ config: context.config,
+ };
+ let preds_str = try_opt!(write_list(items, &fmt));
+
+ Some(format!("{}where\n{}{}",
+ starting_newline,
+ clause_shape.indent.to_string(context.config),
+ preds_str))
+}
+
fn rewrite_where_clause(context: &RewriteContext,
where_clause: &ast::WhereClause,
- config: &Config,
brace_style: BraceStyle,
- indent: Indent,
- width: usize,
+ shape: Shape,
density: Density,
terminator: &str,
- allow_trailing_comma: bool,
+ suppress_comma: bool,
+ snuggle: bool,
span_end: Option<BytePos>)
-> Option<String> {
if where_clause.predicates.is_empty() {
return Some(String::new());
}
- let extra_indent = match context.config.where_indent {
- BlockIndentStyle::Inherit => Indent::empty(),
- BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => Indent::new(config.tab_spaces, 0),
- };
+ if context.config.where_style == Style::Rfc {
+ return rewrite_where_clause_rfc_style(context,
+ where_clause,
+ shape,
+ terminator,
+ suppress_comma,
+ snuggle,
+ span_end);
+ }
+
+ let extra_indent = Indent::new(context.config.tab_spaces, 0);
let offset = match context.config.where_pred_indent {
- BlockIndentStyle::Inherit => indent + extra_indent,
- BlockIndentStyle::Tabbed => indent + extra_indent.block_indent(config),
+ BlockIndentStyle::Tabbed => shape.indent + extra_indent.block_indent(context.config),
// 6 = "where ".len()
- BlockIndentStyle::Visual => indent + extra_indent + 6,
+ BlockIndentStyle::Visual => shape.indent + extra_indent + 6,
};
// FIXME: if where_pred_indent != Visual, then the budgets below might
// be out by a char or two.
terminator,
|pred| span_for_where_pred(pred).lo,
|pred| span_for_where_pred(pred).hi,
- |pred| pred.rewrite(context, budget, offset),
+ |pred| pred.rewrite(context, Shape::legacy(budget, offset)),
span_start,
span_end);
let item_vec = items.collect::<Vec<_>>();
// FIXME: we don't need to collect here if the where_layout isn't
// HorizontalVertical.
let tactic = definitive_tactic(&item_vec, context.config.where_layout, budget);
- let use_trailing_comma = allow_trailing_comma && context.config.where_trailing_comma;
+
+ let mut comma_tactic = context.config.trailing_comma;
+ // Kind of a hack because we don't usually have trailing commas in where clauses.
+ if comma_tactic == SeparatorTactic::Vertical || suppress_comma {
+ comma_tactic = SeparatorTactic::Never;
+ }
let fmt = ListFormatting {
tactic: tactic,
separator: ",",
- trailing_separator: SeparatorTactic::from_bool(use_trailing_comma),
- indent: offset,
- width: budget,
+ trailing_separator: comma_tactic,
+ shape: Shape::legacy(budget, offset),
ends_with_newline: true,
config: context.config,
};
terminator.len()
};
if density == Density::Tall || preds_str.contains('\n') ||
- indent.width() + " where ".len() + preds_str.len() + end_length > width {
+ shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width {
Some(format!("\n{}where {}",
- (indent + extra_indent).to_string(context.config),
+ (shape.indent + extra_indent).to_string(context.config),
preds_str))
} else {
Some(format!(" where {}", preds_str))
-> Option<String> {
let mut result = try_opt!(rewrite_generics(context,
generics,
- offset,
- context.config.max_width,
+ Shape::legacy(context.config.max_width, offset),
generics_offset,
span));
if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result)));
- let where_clause_str = try_opt!(rewrite_where_clause(context,
- &generics.where_clause,
- context.config,
- brace_style,
- context.block_indent,
- budget,
- Density::Tall,
- terminator,
- true,
- Some(span.hi)));
+ let where_clause_str =
+ try_opt!(rewrite_where_clause(context,
+ &generics.where_clause,
+ brace_style,
+ Shape::legacy(budget, offset.block_only()),
+ Density::Tall,
+ terminator,
+ false,
+ trimmed_last_line_width(&result) == 1,
+ Some(span.hi)));
result.push_str(&where_clause_str);
- if !force_same_line_brace &&
+ let same_line_brace = force_same_line_brace ||
+ (generics.where_clause.predicates.is_empty() &&
+ trimmed_last_line_width(&result) == 1);
+ if !same_line_brace &&
(brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine) {
result.push('\n');
- result.push_str(&context.block_indent.to_string(context.config));
+ result.push_str(&offset.block_only().to_string(context.config));
} else {
result.push(' ');
}
result.push_str(opener);
} else {
- if !force_same_line_brace && brace_style == BraceStyle::AlwaysNextLine {
- result.push('\n');
- result.push_str(&context.block_indent.to_string(context.config));
- } else {
+ if force_same_line_brace || trimmed_last_line_width(&result) == 1 ||
+ brace_style != BraceStyle::AlwaysNextLine {
result.push(' ');
+ } else {
+ result.push('\n');
+ result.push_str(&offset.block_only().to_string(context.config));
}
result.push_str(opener);
}