diff --git a/Configurations.md b/Configurations.md index ae8ea2b3c6d2..7f44fa5d3e87 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2188,6 +2188,32 @@ If you want to format code that requires edition 2018, add the following to your edition = "2018" ``` +## `normalize_doc_attributes` + +Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments. + +- **Default value**: `false` +- **Possible values**: `true`, `false` +- **Stable**: No + +#### `false` (default): + +```rust +#![doc = "Example documentation"] + +#[doc = "Example item documentation"] +pub enum Foo {} +``` + +#### `true`: + +```rust +//! Example documentation + +/// Example item documentation +pub enum Foo {} +``` + ## `emit_mode` Internal option diff --git a/src/attr.rs b/src/attr.rs index fc29c69b498c..c7ee633ec4ed 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -10,7 +10,7 @@ //! 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; @@ -350,11 +350,34 @@ impl Rewrite for ast::Attribute { if contains_comment(snippet) { return Some(snippet.to_owned()); } + + let meta = self.meta(); + + // This attribute is possibly a doc attribute needing normalization to a doc comment + if context.config.normalize_doc_attributes() { + if let Some(ref meta) = meta { + if 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( - self.meta() - .and_then(|meta| meta.rewrite(context, shape)) + meta.and_then(|meta| meta.rewrite(context, shape)) .map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)), ) } diff --git a/src/config/mod.rs b/src/config/mod.rs index f240c7b13c68..fca4ca98ddda 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -107,6 +107,7 @@ create_config! { blank_lines_lower_bound: usize, 0, false, "Minimum number of blank lines which must be put between items"; edition: Edition, Edition::Edition2015, false, "The edition of the parser (RFC 2052)"; + normalize_doc_attributes: bool, false, false, "Normalize doc attributes as doc comments"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; diff --git a/tests/source/doc-attrib.rs b/tests/source/doc-attrib.rs new file mode 100644 index 000000000000..f8f2b9566dc1 --- /dev/null +++ b/tests/source/doc-attrib.rs @@ -0,0 +1,11 @@ +// rustfmt-wrap_comments: true +// rustfmt-normalize_doc_attributes: true + +#![doc = "Example doc attribute comment"] + +// Long `#[doc = "..."]` +struct A { #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] b: i32 } + + +#[doc = "The `nodes` and `edges` method each return instantiations of `Cow<[T]>` to leave implementers the freedom to create entirely new vectors or to pass back slices into internally owned vectors."] +struct B { b: i32 } \ No newline at end of file diff --git a/tests/target/doc-attrib.rs b/tests/target/doc-attrib.rs new file mode 100644 index 000000000000..5f77de07de32 --- /dev/null +++ b/tests/target/doc-attrib.rs @@ -0,0 +1,17 @@ +// rustfmt-wrap_comments: true +// rustfmt-normalize_doc_attributes: true + +//! Example doc attribute comment + +// Long `#[doc = "..."]` +struct A { + /// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + b: i32, +} + +/// The `nodes` and `edges` method each return instantiations of `Cow<[T]>` to +/// leave implementers the freedom to create entirely new vectors or to pass +/// back slices into internally owned vectors. +struct B { + b: i32, +}