]> git.lizzy.rs Git - rust.git/blobdiff - src/lists.rs
Preserve trailing comma on macro call when using mixed layout
[rust.git] / src / lists.rs
index fdb022db077ff7c4610980f92dee2cc6106de16b..a14d1907a8c169ecb912b05a660be47ff45af72f 100644 (file)
@@ -56,7 +56,7 @@ fn as_ref(&self) -> &ListItem {
     }
 }
 
-#[derive(PartialEq, Eq, Debug)]
+#[derive(PartialEq, Eq, Debug, Copy, Clone)]
 pub enum ListItemCommentStyle {
     // Try to keep the comment on the same line with the item.
     SameLine,
@@ -66,7 +66,7 @@ pub enum ListItemCommentStyle {
     None,
 }
 
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 pub struct ListItem {
     // None for comments mean that they are not present.
     pub pre_comment: Option<String>,
@@ -101,7 +101,7 @@ pub fn is_multiline(&self) -> bool {
                 .map_or(false, |s| s.contains('\n'))
     }
 
-    pub fn has_comment(&self) -> bool {
+    pub fn has_single_line_comment(&self) -> bool {
         self.pre_comment
             .as_ref()
             .map_or(false, |comment| comment.trim_left().starts_with("//"))
@@ -110,6 +110,10 @@ pub fn has_comment(&self) -> bool {
                 .map_or(false, |comment| comment.trim_left().starts_with("//"))
     }
 
+    pub fn has_comment(&self) -> bool {
+        self.pre_comment.is_some() || self.post_comment.is_some()
+    }
+
     pub fn from_str<S: Into<String>>(s: S) -> ListItem {
         ListItem {
             pre_comment: None,
@@ -164,15 +168,14 @@ pub fn definitive_tactic<I, T>(
     let pre_line_comments = items
         .clone()
         .into_iter()
-        .any(|item| item.as_ref().has_comment());
+        .any(|item| item.as_ref().has_single_line_comment());
 
     let limit = match tactic {
         _ if pre_line_comments => return DefinitiveListTactic::Vertical,
-        ListTactic::Mixed => return DefinitiveListTactic::Mixed,
         ListTactic::Horizontal => return DefinitiveListTactic::Horizontal,
         ListTactic::Vertical => return DefinitiveListTactic::Vertical,
         ListTactic::LimitedHorizontalVertical(limit) => ::std::cmp::min(width, limit),
-        ListTactic::HorizontalVertical => width,
+        ListTactic::Mixed | ListTactic::HorizontalVertical => width,
     };
 
     let (sep_count, total_width) = calculate_width(items.clone());
@@ -184,7 +187,10 @@ pub fn definitive_tactic<I, T>(
     {
         DefinitiveListTactic::Horizontal
     } else {
-        DefinitiveListTactic::Vertical
+        match tactic {
+            ListTactic::Mixed => DefinitiveListTactic::Mixed,
+            _ => DefinitiveListTactic::Vertical,
+        }
     }
 }
 
@@ -253,7 +259,9 @@ pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
                     result.push(' ');
                 }
             }
-            DefinitiveListTactic::Vertical if !first => {
+            DefinitiveListTactic::Vertical
+                if !first && !inner_item.is_empty() && !result.is_empty() =>
+            {
                 result.push('\n');
                 result.push_str(indent_str);
             }
@@ -266,14 +274,14 @@ pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
                     result.push_str(indent_str);
                     line_len = 0;
                     if formatting.ends_with_newline {
-                        if last {
-                            separate = true;
-                        } else {
-                            trailing_separator = true;
-                        }
+                        trailing_separator = true;
                     }
                 }
 
+                if last && formatting.ends_with_newline {
+                    separate = formatting.trailing_separator != SeparatorTactic::Never;
+                }
+
                 if line_len > 0 {
                     result.push(' ');
                     line_len += 1;
@@ -609,6 +617,8 @@ fn next(&mut self) -> Option<Self::Item> {
 
             let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') {
                 post_snippet[1..].trim_matches(white_space)
+            } else if post_snippet.starts_with(self.separator) {
+                post_snippet[self.separator.len()..].trim_matches(white_space)
             } else if post_snippet.ends_with(',') {
                 post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space)
             } else {