]> git.lizzy.rs Git - rust.git/commitdiff
Preserve blank line between doc comment and attribute
authortopecongiro <seuchida@gmail.com>
Sun, 27 Aug 2017 15:17:38 +0000 (00:17 +0900)
committertopecongiro <seuchida@gmail.com>
Sun, 27 Aug 2017 15:17:38 +0000 (00:17 +0900)
src/visitor.rs

index bf1afb0c3f09f86117d93e02239107b36bcd64d1..e6872078365903fd4b776f9ef8aa568b1747e5a9 100644 (file)
@@ -18,7 +18,8 @@
 
 use {Indent, Shape, Spanned};
 use codemap::{LineRangeUtils, SpanUtils};
-use comment::{contains_comment, CodeCharKind, CommentCodeSlices, FindUncommented};
+use comment::{contains_comment, recover_missing_comment_in_span, CodeCharKind, CommentCodeSlices,
+              FindUncommented};
 use comment::rewrite_comment;
 use config::{BraceStyle, Config};
 use expr::{format_expr, ExprType};
@@ -928,6 +929,8 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
         let mut derive_args = Vec::new();
 
         let mut iter = self.iter().enumerate().peekable();
+        let mut insert_new_line = true;
+        let mut is_prev_sugared_doc = false;
         while let Some((i, a)) = iter.next() {
             let a_str = try_opt!(a.rewrite(context, shape));
 
@@ -937,31 +940,61 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                 // This particular horror show is to preserve line breaks in between doc
                 // comments. An alternative would be to force such line breaks to start
                 // with the usual doc comment token.
-                let multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1;
-                let comment = comment.trim();
+                let (multi_line_before, multi_line_after) = if a.is_sugared_doc ||
+                    is_prev_sugared_doc
+                {
+                    // Look at before and after comment and see if there are any empty lines.
+                    let comment_begin = comment.chars().position(|c| c == '/');
+                    let len = comment_begin.unwrap_or(comment.len());
+                    let mlb = comment.chars().take(len).filter(|c| *c == '\n').count() > 1;
+                    let mla = if comment_begin.is_none() {
+                        mlb
+                    } else {
+                        let comment_end = comment.chars().rev().position(|c| !c.is_whitespace());
+                        let len = comment_end.unwrap();
+                        comment
+                            .chars()
+                            .rev()
+                            .take(len)
+                            .filter(|c| *c == '\n')
+                            .count() > 1
+                    };
+                    (mlb, mla)
+                } else {
+                    (false, false)
+                };
+
+                let comment = try_opt!(recover_missing_comment_in_span(
+                    mk_sp(self[i - 1].span.hi, a.span.lo),
+                    shape.with_max_width(context.config),
+                    context,
+                    0,
+                ));
+
                 if !comment.is_empty() {
-                    let comment = try_opt!(rewrite_comment(
-                        comment,
-                        false,
-                        Shape::legacy(
-                            context.config.comment_width() - shape.indent.width(),
-                            shape.indent,
-                        ),
-                        context.config,
-                    ));
-                    result.push_str(&indent);
+                    if multi_line_before {
+                        result.push('\n');
+                    }
                     result.push_str(&comment);
                     result.push('\n');
-                } else if multi_line {
+                    if multi_line_after {
+                        result.push('\n')
+                    }
+                } else if insert_new_line {
                     result.push('\n');
+                    if multi_line_after {
+                        result.push('\n')
+                    }
                 }
+
                 if derive_args.is_empty() {
                     result.push_str(&indent);
                 }
+
+                insert_new_line = true;
             }
 
             // Write the attribute itself.
-            let mut insert_new_line = true;
             if context.config.merge_derives() {
                 // If the attribute is `#[derive(...)]`, take the arguments.
                 if let Some(mut args) = get_derive_args(context, a) {
@@ -982,9 +1015,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                 result.push_str(&a_str);
             }
 
-            if insert_new_line && i < self.len() - 1 {
-                result.push('\n');
-            }
+            is_prev_sugared_doc = a.is_sugared_doc;
         }
         Some(result)
     }