use syntax::ast;
use syntax::codemap::{BytePos, Span};
-use {Indent, Shape, Spanned};
+use spanned::Spanned;
use codemap::SpanUtils;
-use comment::contains_comment;
+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, mk_sp};
+use shape::{Indent, Shape};
+use utils::{contains_skip, is_attributes_extendable, mk_sp};
pub trait AlignedItem {
fn skip(&self) -> bool;
}
fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
- rewrite_struct_field_prefix(context, self, shape)
+ let attrs_str = self.attrs.rewrite(context, shape)?;
+ let missing_span = if self.attrs.is_empty() {
+ mk_sp(self.span.lo(), self.span.lo())
+ } else {
+ mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo())
+ };
+ let attrs_extendable = context.config.attributes_on_same_line_as_field()
+ && is_attributes_extendable(&attrs_str);
+ rewrite_struct_field_prefix(context, self).and_then(|field_str| {
+ combine_strs_with_missing_comments(
+ context,
+ &attrs_str,
+ &field_str,
+ missing_span,
+ shape,
+ attrs_extendable,
+ )
+ })
}
fn rewrite_aligned_item(
}
fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
- let mut attrs_str = try_opt!(self.attrs.rewrite(context, shape));
- if !attrs_str.is_empty() {
- attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config)));
- };
+ let attrs_str = self.attrs.rewrite(context, shape)?;
let name = &self.ident.node.to_string();
- Some(format!("{}{}", attrs_str, name))
+ let missing_span = if self.attrs.is_empty() {
+ mk_sp(self.span.lo(), self.span.lo())
+ } else {
+ mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo())
+ };
+ combine_strs_with_missing_comments(
+ context,
+ &attrs_str,
+ name,
+ missing_span,
+ shape,
+ is_attributes_extendable(&attrs_str),
+ )
}
fn rewrite_aligned_item(
let init = &fields[0..group_index + 1];
let rest = &fields[group_index + 1..];
let init_last_pos = if rest.is_empty() {
- span.hi
+ span.hi()
} else {
// Decide whether the missing comments should stick to init or rest.
- let init_hi = init[init.len() - 1].get_span().hi;
- let rest_lo = rest[0].get_span().lo;
+ let init_hi = init[init.len() - 1].get_span().hi();
+ let rest_lo = rest[0].get_span().lo();
let missing_span = mk_sp(init_hi, rest_lo);
let missing_span = mk_sp(
context.codemap.span_after(missing_span, ","),
- missing_span.hi,
+ missing_span.hi(),
);
let snippet = context.snippet(missing_span);
init_hi + BytePos(offset as u32 + 2)
} else {
- missing_span.lo
+ missing_span.lo()
}
};
- let init_span = mk_sp(span.lo, init_last_pos);
+ let init_span = mk_sp(span.lo(), init_last_pos);
let one_line_width = if rest.is_empty() { one_line_width } else { 0 };
- let result = try_opt!(rewrite_aligned_items_inner(
- context,
- init,
- init_span,
- shape.indent,
- one_line_width,
- ));
+ let result =
+ rewrite_aligned_items_inner(context, init, init_span, shape.indent, one_line_width)?;
if rest.is_empty() {
Some(result + spaces)
} else {
- let rest_span = mk_sp(init_last_pos, span.hi);
- let rest_str = try_opt!(rewrite_with_alignment(
- rest,
- context,
- shape,
- rest_span,
- one_line_width,
- ));
+ let rest_span = mk_sp(init_last_pos, span.hi());
+ let rest_str = rewrite_with_alignment(rest, context, shape, rest_span, one_line_width)?;
Some(
- result + spaces + "\n" +
- &shape
+ result + spaces + "\n"
+ + &shape
.indent
.block_indent(context.config)
.to_string(context.config) + &rest_str,
}
}
-fn struct_field_preix_max_min_width<T: AlignedItem>(
+fn struct_field_prefix_max_min_width<T: AlignedItem>(
context: &RewriteContext,
fields: &[T],
shape: Shape,
fields
.iter()
.map(|field| {
- field.rewrite_prefix(context, shape).and_then(
- |field_str| if field_str.contains('\n') {
+ field.rewrite_prefix(context, shape).and_then(|field_str| {
+ if field_str.contains('\n') {
None
} else {
Some(field_str.len())
- },
- )
+ }
+ })
})
.fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) {
(Some((max_len, min_len)), Some(len)) => {
) -> Option<String> {
let item_indent = offset.block_indent(context.config);
// 1 = ","
- let item_shape = try_opt!(Shape::indented(item_indent, context.config).sub_width(1));
+ let item_shape = Shape::indented(item_indent, context.config).sub_width(1)?;
let (mut field_prefix_max_width, field_prefix_min_width) =
- struct_field_preix_max_min_width(context, fields, item_shape);
+ struct_field_prefix_max_min_width(context, fields, item_shape);
let max_diff = field_prefix_max_width
.checked_sub(field_prefix_min_width)
.unwrap_or(0);
context.codemap,
fields.iter(),
"}",
- |field| field.get_span().lo,
- |field| field.get_span().hi,
+ |field| field.get_span().lo(),
+ |field| field.get_span().hi(),
|field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width),
- span.lo,
- span.hi,
+ span.lo(),
+ span.hi(),
+ false,
).collect::<Vec<_>>();
let tactic = definitive_tactic(
tactic: tactic,
separator: ",",
trailing_separator: context.config.trailing_comma(),
+ separator_place: SeparatorPlace::Back,
shape: item_shape,
ends_with_newline: true,
preserve_newline: true,
return ("", index);
}
// See if there are comments or empty lines between fields.
- let span = mk_sp(fields[i].get_span().hi, fields[i + 1].get_span().lo);
+ let span = mk_sp(fields[i].get_span().hi(), fields[i + 1].get_span().lo());
let snippet = context
.snippet(span)
.lines()
.skip(1)
.collect::<Vec<_>>()
.join("\n");
- let spacings = if snippet
- .lines()
- .rev()
- .skip(1)
- .find(|l| l.trim().is_empty())
- .is_some()
- {
+ let spacings = if snippet.lines().rev().skip(1).any(|l| l.trim().is_empty()) {
"\n"
} else {
""