]> git.lizzy.rs Git - rust.git/commitdiff
Support pre- and post-comments for enums
authormwiczer <wiczerm@gmail.com>
Wed, 7 Oct 2015 23:23:07 +0000 (19:23 -0400)
committermwiczer <wiczerm@gmail.com>
Thu, 8 Oct 2015 21:22:57 +0000 (17:22 -0400)
Use lists to format enum variants rather than special formatting.
Add tests for enums mostly around block comments.

src/items.rs
src/lists.rs
tests/source/enum.rs [new file with mode: 0644]
tests/source/structs.rs
tests/target/enum.rs
tests/target/structs.rs

index 3d9a0e56aa46439cacce974da6e578d7d612ff8c..816bfac0fb3ce9dde6f996c7336694b9ee2ccc4a 100644 (file)
@@ -592,31 +592,88 @@ pub fn visit_enum(&mut self,
         self.buffer.push_str(&generics_str);
 
         self.last_pos = body_start;
-        self.block_indent = self.block_indent.block_indent(self.config);
-        for (i, f) in enum_def.variants.iter().enumerate() {
-            let next_span_start: BytePos = if i == enum_def.variants.len() - 1 {
-                span.hi
-            } else {
-                enum_def.variants[i + 1].span.lo
-            };
 
-            self.visit_variant(f, i == enum_def.variants.len() - 1, next_span_start);
+        self.block_indent = self.block_indent.block_indent(self.config);
+        let variant_list = self.format_variant_list(enum_def, body_start, span.hi - BytePos(1));
+        match variant_list {
+            Some(ref body_str) => self.buffer.push_str(&body_str),
+            None => self.format_missing(span.hi - BytePos(1)),
         }
         self.block_indent = self.block_indent.block_unindent(self.config);
 
-        self.format_missing_with_indent(span.hi - BytePos(1));
+        if variant_list.is_some() {
+            self.buffer.push_str(&self.block_indent.to_string(self.config));
+        }
         self.buffer.push_str("}");
+        self.last_pos = span.hi;
+    }
+
+    // Format the body of an enum definition
+    fn format_variant_list(&self,
+                           enum_def: &ast::EnumDef,
+                           body_lo: BytePos,
+                           body_hi: BytePos)
+                           -> Option<String> {
+        if enum_def.variants.is_empty() {
+            return None;
+        }
+        let mut result = String::with_capacity(1024);
+        result.push('\n');
+        let indentation = self.block_indent.to_string(self.config);
+        result.push_str(&indentation);
+
+        let items = itemize_list(self.codemap,
+                                 enum_def.variants.iter(),
+                                 "}",
+                                 |f| {
+                                     if !f.node.attrs.is_empty() {
+                                         f.node.attrs[0].span.lo
+                                     } else {
+                                         f.span.lo
+                                     }
+                                 },
+                                 |f| f.span.hi,
+                                 |f| self.format_variant(f),
+                                 body_lo,
+                                 body_hi);
+
+        let budget = self.config.max_width - self.block_indent.width() - 2;
+        let fmt = ListFormatting {
+            tactic: DefinitiveListTactic::Vertical,
+            separator: ",",
+            trailing_separator: SeparatorTactic::Always,
+            indent: self.block_indent,
+            width: budget,
+            ends_with_newline: true,
+            config: self.config,
+        };
+
+        let list = try_opt!(write_list(items, &fmt));
+        result.push_str(&list);
+        result.push('\n');
+        Some(result)
     }
 
     // Variant of an enum.
-    fn visit_variant(&mut self, field: &ast::Variant, last_field: bool, next_span_start: BytePos) {
-        if self.visit_attrs(&field.node.attrs) {
-            return;
+    fn format_variant(&self, field: &ast::Variant) -> Option<String> {
+        if contains_skip(&field.node.attrs) {
+            let lo = field.node.attrs[0].span.lo;
+            let span = codemap::mk_sp(lo, field.span.hi);
+            return Some(self.snippet(span));
         }
 
-        self.format_missing_with_indent(field.span.lo);
+        let indent = self.block_indent;
+        let mut result = try_opt!(field.node
+                                       .attrs
+                                       .rewrite(&self.get_context(),
+                                                self.config.max_width - indent.width(),
+                                                indent));
+        if !result.is_empty() {
+            result.push('\n');
+            result.push_str(&indent.to_string(self.config));
+        }
 
-        let result = match field.node.kind {
+        let variant_body = match field.node.kind {
             ast::VariantKind::TupleVariantKind(ref types) => {
                 let mut result = field.node.name.to_string();
 
@@ -633,12 +690,12 @@ fn visit_variant(&mut self, field: &ast::Variant, last_field: bool, next_span_st
                                                                 Indent::empty())
                                              },
                                              span_after(field.span, "(", self.codemap),
-                                             next_span_start);
+                                             field.span.hi);
                     let item_vec = items.collect::<Vec<_>>();
 
                     result.push('(');
 
-                    let indent = self.block_indent + field.node.name.to_string().len() + "(".len();
+                    let indent = indent + field.node.name.to_string().len() + "(".len();
 
                     let comma_cost = if self.config.enum_trailing_comma {
                         1
@@ -659,10 +716,7 @@ fn visit_variant(&mut self, field: &ast::Variant, last_field: bool, next_span_st
                         ends_with_newline: true,
                         config: self.config,
                     };
-                    let list_str = match write_list(&item_vec, &fmt) {
-                        Some(list_str) => list_str,
-                        None => return,
-                    };
+                    let list_str = try_opt!(write_list(&item_vec, &fmt));
 
                     result.push_str(&list_str);
                     result.push(')');
@@ -674,31 +728,26 @@ fn visit_variant(&mut self, field: &ast::Variant, last_field: bool, next_span_st
                     result.push_str(&expr_snippet);
                 }
 
-                result
+                Some(result)
             }
             ast::VariantKind::StructVariantKind(ref struct_def) => {
                 // TODO: Should limit the width, as we have a trailing comma
-                let struct_rewrite = self.format_struct("",
-                                                        field.node.name,
-                                                        ast::Visibility::Inherited,
-                                                        struct_def,
-                                                        None,
-                                                        field.span,
-                                                        self.block_indent);
-
-                match struct_rewrite {
-                    Some(struct_str) => struct_str,
-                    None => return,
-                }
+                self.format_struct("",
+                                   field.node.name,
+                                   ast::Visibility::Inherited,
+                                   struct_def,
+                                   None,
+                                   field.span,
+                                   indent)
             }
         };
-        self.buffer.push_str(&result);
 
-        if !last_field || self.config.enum_trailing_comma {
-            self.buffer.push_str(",");
+        if let Some(variant_str) = variant_body {
+            result.push_str(&variant_str);
+            Some(result)
+        } else {
+            None
         }
-
-        self.last_pos = field.span.hi + BytePos(1);
     }
 
     fn format_struct(&self,
index 6f464805e4b7b71feb2479260d607ad94c9d7d59..35705611f1e29d7901025de2d30d93ac8be82f55 100644 (file)
@@ -208,7 +208,18 @@ pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option
         } else {
             0
         };
-        let item_width = inner_item.len() + item_sep_len;
+
+        // Item string may be multi-line. Its length (used for block comment alignment)
+        // Should be only the length of the last line.
+        let item_last_line = if item.is_multiline() {
+            inner_item.lines().last().unwrap_or("")
+        } else {
+            inner_item.as_ref()
+        };
+        let mut item_last_line_width = item_last_line.len() + item_sep_len;
+        if item_last_line.starts_with(indent_str) {
+            item_last_line_width -= indent_str.len();
+        }
 
         match tactic {
             DefinitiveListTactic::Horizontal if !first => {
@@ -284,10 +295,12 @@ pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option
 
         if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() {
             // 1 = space between item and comment.
-            let width = formatting.width.checked_sub(item_width + 1).unwrap_or(1);
+            let width = formatting.width.checked_sub(item_last_line_width + 1).unwrap_or(1);
             let mut offset = formatting.indent;
-            offset.alignment += item_width + 1;
+            offset.alignment += item_last_line_width + 1;
             let comment = item.post_comment.as_ref().unwrap();
+
+            debug!("Width = {}, offset = {:?}", width, offset);
             // Use block-style only for the last item or multiline comments.
             let block_style = !formatting.ends_with_newline && last ||
                               comment.trim().contains('\n') ||
diff --git a/tests/source/enum.rs b/tests/source/enum.rs
new file mode 100644 (file)
index 0000000..30b1dda
--- /dev/null
@@ -0,0 +1,94 @@
+// Enums test
+
+#[atrr]
+pub enum Test {
+    A, B(u32, 
+         A /* comment */, 
+         SomeType),
+    /// Doc comment
+    C,
+}
+
+pub enum Foo<'a, Y: Baz> where X: Whatever
+{ A, }
+
+enum EmtpyWithComment {
+    // Some comment
+}
+
+// C-style enum
+enum Bar {
+    A = 1,
+    #[someAttr(test)]
+    B = 2, // comment
+    C,
+}
+
+enum LongVariants {
+First(LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment
+VARIANT),
+    // This is the second variant
+    Second
+}
+
+enum StructLikeVariants {
+    Normal(u32, String, ),
+    StructLike { x: i32, // Test comment
+        // Pre-comment
+        #[Attr50] y: SomeType, // Aanother Comment
+    }, SL { a: A }
+}
+
+enum X {
+    CreateWebGLPaintTask(Size2D<i32>, GLContextAttributes, IpcSender<Result<(IpcSender<CanvasMsg>, usize), String>>), // This is a post comment
+}
+
+pub enum EnumWithAttributes {
+    //This is a pre comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+    TupleVar(usize, usize, usize), // AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+    // Pre Comment
+    #[rustfmt_skip]
+    SkippedItem(String,String,), // Post-comment
+    #[another_attr]
+    #[attr2]
+    ItemStruct {x: usize, y: usize}, // Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+    // And another
+    ForcedPreflight // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+}
+
+pub enum SingleTuple {
+    // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+    Match(usize, usize, String) // Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+}
+
+pub enum SingleStruct {
+    Match {name: String, loc: usize} // Post-comment
+}
+
+pub enum GenericEnum<I, T>
+where I: Iterator<Item = T> {
+    // Pre Comment
+    Left {list: I, root: T}, // Post-comment
+    Right {list: I, root: T} // Post Comment
+}
+
+
+enum EmtpyWithComment {
+    // Some comment
+}
+
+enum TestFormatFails {
+    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+}
+
+fn nested_enum_test() {
+    if true {
+        enum TestEnum {
+            One(usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize,), // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA
+            Two // AAAAAAAAAAAAAAAAAA  AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAA
+        }
+        enum TestNestedFormatFail {
+            AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        }
+    }
+}
index bd9db77fec0ba7a5c5fdda891f1447aa090fcb61..26578bf8c23acac28eeeebe107f1fecaedaf8ff8 100644 (file)
@@ -105,3 +105,13 @@ pub struct State<F: FnMut()> { now: F }
 
 struct Palette { /// A map of indizes in the palette to a count of pixels in approximately that color
                     foo: i32}
+
+// Splitting a single line comment into a block previously had a misalignment
+// when the field had attributes
+struct FieldsWithAttributes {
+    // Pre Comment
+    #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB
+    //Another pre comment
+    #[attr1]
+    #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC
+}
index aca9ec42af4da7ad8ee7dd4040da5005f893ce87..72a0266b23c344668693e6aa730488fa954aacf4 100644 (file)
@@ -49,5 +49,94 @@ enum StructLikeVariants {
 enum X {
     CreateWebGLPaintTask(Size2D<i32>,
                          GLContextAttributes,
-                         IpcSender<Result<(IpcSender<CanvasMsg>, usize), String>>),
+                         IpcSender<Result<(IpcSender<CanvasMsg>, usize), String>>), /* This is
+                                                                                     * a post c
+                                                                                     * omment */
+}
+
+pub enum EnumWithAttributes {
+    // This is a pre comment
+    // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+    TupleVar(usize, usize, usize), /* AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA
+                                    * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */
+    // Pre Comment
+    #[rustfmt_skip]
+    SkippedItem(String,String,), // Post-comment
+    #[another_attr]
+    #[attr2]
+    ItemStruct {
+        x: usize,
+        y: usize,
+    }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        * AAAAAAAAAAAAAAAAAAA */
+    // And another
+    ForcedPreflight, /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+                      * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */
+}
+
+pub enum SingleTuple {
+    // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+    // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+    Match(usize, usize, String), /* Post-comment
+                                  * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+                                  * A */
+}
+
+pub enum SingleStruct {
+    Match {
+        name: String,
+        loc: usize,
+    }, // Post-comment
+}
+
+pub enum GenericEnum<I, T>
+    where I: Iterator<Item = T>
+{
+    // Pre Comment
+    Left {
+        list: I,
+        root: T,
+    }, // Post-comment
+    Right {
+        list: I,
+        root: T,
+    }, // Post Comment
+}
+
+
+enum EmtpyWithComment {
+    // Some comment
+}
+
+enum TestFormatFails {
+    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+}
+
+fn nested_enum_test() {
+    if true {
+        enum TestEnum {
+            One(usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize,
+                usize), /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA
+                         * AAAAAAAAAAAAAAAAAAAAAA */
+            Two, /* AAAAAAAAAAAAAAAAAA  AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+                  * AAAAAAAAAAAAAAAAAA */
+        }
+        enum TestNestedFormatFail {
+            AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        }
+    }
 }
index 67060ddf80ed35955cb9bd2278a817cc90ac43a3..5ea4a21bad5dbef82b741dbe946f5bd3ce04b524 100644 (file)
@@ -100,3 +100,16 @@ struct Palette {
     /// A map of indizes in the palette to a count of pixels in approximately that color
     foo: i32,
 }
+
+// Splitting a single line comment into a block previously had a misalignment
+// when the field had attributes
+struct FieldsWithAttributes {
+    // Pre Comment
+    #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB
+                                      * BBBBBBBBBBBBBBBBB BBBBBBBBBBB */
+    // Another pre comment
+    #[attr1]
+    #[attr2]
+    pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC
+                    * CCCCCCCCCCCCCC CCCCCCCCCCCC */
+}