]> git.lizzy.rs Git - rust.git/blobdiff - src/attr.rs
Fixup formatting
[rust.git] / src / attr.rs
index 6aa62f40db2440122719be9605bc58c2c9dfa21c..033f3767ecdcf3e50ac9fdb092f94b5c6d2c8473 100644 (file)
 
 //! Format attributes and meta items.
 
-use comment::{contains_comment, rewrite_doc_comment};
+use comment::{contains_comment, rewrite_doc_comment, CommentStyle};
 use config::lists::*;
 use config::IndentStyle;
 use expr::rewrite_literal;
-use lists::{itemize_list, write_list, ListFormatting};
+use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
+use overflow;
 use rewrite::{Rewrite, RewriteContext};
 use shape::Shape;
 use types::{rewrite_path, PathContext};
 use utils::{count_newlines, mk_sp};
 
-use std::borrow::Cow;
 use syntax::ast;
-use syntax::codemap::{BytePos, Span, DUMMY_SP};
+use syntax::source_map::{BytePos, Span, DUMMY_SP};
 
 /// Returns attributes on the given statement.
 pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] {
@@ -48,7 +48,7 @@ fn is_derive(attr: &ast::Attribute) -> bool {
 }
 
 /// Returns the arguments of `#[derive(...)]`.
-fn get_derive_spans<'a>(attr: &ast::Attribute) -> Option<Vec<Span>> {
+fn get_derive_spans(attr: &ast::Attribute) -> Option<Vec<Span>> {
     attr.meta_item_list().map(|meta_item_list| {
         meta_item_list
             .iter()
@@ -61,15 +61,22 @@ fn get_derive_spans<'a>(attr: &ast::Attribute) -> Option<Vec<Span>> {
 fn argument_shape(
     left: usize,
     right: usize,
+    combine: bool,
     shape: Shape,
     context: &RewriteContext,
 ) -> Option<Shape> {
     match context.config.indent_style() {
-        IndentStyle::Block => Some(
-            shape
-                .block_indent(context.config.tab_spaces())
-                .with_max_width(context.config),
-        ),
+        IndentStyle::Block => {
+            if combine {
+                shape.offset_left(left)
+            } else {
+                Some(
+                    shape
+                        .block_indent(context.config.tab_spaces())
+                        .with_max_width(context.config),
+                )
+            }
+        }
         IndentStyle::Visual => shape
             .visual_indent(0)
             .shrink_left(left)
@@ -87,7 +94,7 @@ fn format_derive(
     result.push_str(prefix);
     result.push_str("[derive(");
 
-    let argument_shape = argument_shape(10 + prefix.len(), 2, shape, context)?;
+    let argument_shape = argument_shape(10 + prefix.len(), 2, false, shape, context)?;
     let item_str = format_arg_list(
         derive_args.iter(),
         |_| DUMMY_SP.lo(),
@@ -98,6 +105,8 @@ fn format_derive(
         argument_shape,
         // 10 = "[derive()]", 3 = "()" and "]"
         shape.offset_left(10 + prefix.len())?.sub_width(3)?,
+        None,
+        false,
     )?;
 
     result.push_str(&item_str);
@@ -193,7 +202,8 @@ fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) {
             .rev()
             .take_while(|c| c.is_whitespace())
             .filter(|&c| c == '\n')
-            .count() > 1
+            .count()
+            > 1
     };
     (if mlb { "\n" } else { "" }, if mla { "\n" } else { "" })
 }
@@ -206,36 +216,21 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
             }
             ast::MetaItemKind::List(ref list) => {
                 let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?;
-
-                let snippet = context.snippet(self.span);
-                // 2 = )] (this might go wrong if there is whitespace between the brackets, but
-                // it's close enough).
-                let snippet = snippet[..snippet.len() - 2].trim();
-                let trailing_comma = if snippet.ends_with(',') { "," } else { "" };
-
-                let argument_shape =
-                    argument_shape(path.len() + 1, 2 + trailing_comma.len(), shape, context)?;
-                let item_str = format_arg_list(
+                let has_trailing_comma = ::expr::span_ends_with_comma(context, self.span);
+                overflow::rewrite_with_parens(
+                    context,
+                    &path,
                     list.iter(),
-                    |nested_meta_item| nested_meta_item.span.lo(),
-                    |nested_meta_item| nested_meta_item.span.hi(),
-                    |nested_meta_item| nested_meta_item.rewrite(context, argument_shape),
+                    // 1 = "]"
+                    shape.sub_width(1)?,
                     self.span,
-                    context,
-                    argument_shape,
-                    // 3 = "()" and "]"
-                    shape
-                        .offset_left(path.len())?
-                        .sub_width(3 + trailing_comma.len())?,
-                )?;
-
-                let indent = if item_str.starts_with('\n') {
-                    shape.indent.to_string_with_newline(context.config)
-                } else {
-                    Cow::Borrowed("")
-                };
-
-                format!("{}({}{}{})", path, item_str, trailing_comma, indent)
+                    context.config.width_heuristics().attr_fn_like_width,
+                    Some(if has_trailing_comma {
+                        SeparatorTactic::Always
+                    } else {
+                        SeparatorTactic::Never
+                    }),
+                )?
             }
             ast::MetaItemKind::NameValue(ref literal) => {
                 let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?;
@@ -264,6 +259,8 @@ fn format_arg_list<I, T, F1, F2, F3>(
     context: &RewriteContext,
     shape: Shape,
     one_line_shape: Shape,
+    one_line_limit: Option<usize>,
+    combine: bool,
 ) -> Option<String>
 where
     I: Iterator<Item = T>,
@@ -284,27 +281,21 @@ fn format_arg_list<I, T, F1, F2, F3>(
         false,
     );
     let item_vec = items.collect::<Vec<_>>();
-    let tactic = ::lists::definitive_tactic(
-        &item_vec,
-        ListTactic::HorizontalVertical,
-        ::lists::Separator::Comma,
-        shape.width,
-    );
-    let fmt = ListFormatting {
-        tactic,
-        separator: ",",
-        trailing_separator: SeparatorTactic::Never,
-        separator_place: SeparatorPlace::Back,
-        shape,
-        ends_with_newline: false,
-        preserve_newline: false,
-        nested: false,
-        config: context.config,
+    let tactic = if let Some(limit) = one_line_limit {
+        ListTactic::LimitedHorizontalVertical(limit)
+    } else {
+        ListTactic::HorizontalVertical
     };
+
+    let tactic = definitive_tactic(&item_vec, tactic, Separator::Comma, shape.width);
+    let fmt = ListFormatting::new(shape, context.config)
+        .tactic(tactic)
+        .ends_with_newline(false);
     let item_str = write_list(&item_vec, &fmt)?;
 
     let one_line_budget = one_line_shape.width;
     if context.config.indent_style() == IndentStyle::Visual
+        || combine
         || (!item_str.contains('\n') && item_str.len() <= one_line_budget)
     {
         Some(item_str)
@@ -325,13 +316,34 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
             if contains_comment(snippet) {
                 return Some(snippet.to_owned());
             }
-            // 1 = `[`
-            let shape = shape.offset_left(prefix.len() + 1)?;
-            Some(
-                self.meta()
-                    .and_then(|meta| meta.rewrite(context, shape))
-                    .map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)),
-            )
+
+            if let Some(ref meta) = self.meta() {
+                // This attribute is possibly a doc attribute needing normalization to a doc comment
+                if context.config.normalize_doc_attributes() && meta.check_name("doc") {
+                    if let Some(ref literal) = meta.value_str() {
+                        let comment_style = match self.style {
+                            ast::AttrStyle::Inner => CommentStyle::Doc,
+                            ast::AttrStyle::Outer => CommentStyle::TripleSlash,
+                        };
+
+                        let doc_comment = format!("{}{}", comment_style.opener(), literal);
+                        return rewrite_doc_comment(
+                            &doc_comment,
+                            shape.comment(context.config),
+                            context.config,
+                        );
+                    }
+                }
+
+                // 1 = `[`
+                let shape = shape.offset_left(prefix.len() + 1)?;
+                Some(
+                    meta.rewrite(context, shape)
+                        .map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)),
+                )
+            } else {
+                Some(snippet.to_owned())
+            }
         }
     }
 }