]> git.lizzy.rs Git - rust.git/blobdiff - src/vertical.rs
Merge pull request #2138 from topecongiro/comments-around-trait-bounds
[rust.git] / src / vertical.rs
index 57876d644c23e777fa586d9520620ad2d517ec57..32072acfc9e6d243b809e2b345ff34d626331860 100644 (file)
 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};
+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;
@@ -46,7 +48,24 @@ fn get_span(&self) -> Span {
     }
 
     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(
@@ -69,12 +88,21 @@ fn get_span(&self) -> Span {
     }
 
     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(
@@ -102,15 +130,15 @@ pub fn rewrite_with_alignment<T: AlignedItem>(
     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);
@@ -133,32 +161,21 @@ pub fn rewrite_with_alignment<T: AlignedItem>(
 
             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,
@@ -166,7 +183,7 @@ pub fn rewrite_with_alignment<T: AlignedItem>(
     }
 }
 
-fn struct_field_preix_max_min_width<T: AlignedItem>(
+fn struct_field_prefix_max_min_width<T: AlignedItem>(
     context: &RewriteContext,
     fields: &[T],
     shape: Shape,
@@ -174,13 +191,13 @@ fn struct_field_preix_max_min_width<T: AlignedItem>(
     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)) => {
@@ -200,9 +217,9 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
 ) -> 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);
@@ -214,19 +231,26 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
         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(&items, ListTactic::HorizontalVertical, one_line_width);
+    let tactic = definitive_tactic(
+        &items,
+        ListTactic::HorizontalVertical,
+        Separator::Comma,
+        one_line_width,
+    );
 
     let fmt = ListFormatting {
         tactic: tactic,
         separator: ",",
         trailing_separator: context.config.trailing_comma(),
+        separator_place: SeparatorPlace::Back,
         shape: item_shape,
         ends_with_newline: true,
         preserve_newline: true,
@@ -245,20 +269,14 @@ fn group_aligned_items<T: AlignedItem>(
             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 {
             ""