Skip to content

Commit

Permalink
Partition wrap_comments into normal or doc settings
Browse files Browse the repository at this point in the history
  • Loading branch information
Nemo157 committed Feb 5, 2024
1 parent ead0fc9 commit 4c0eba4
Show file tree
Hide file tree
Showing 18 changed files with 299 additions and 26 deletions.
12 changes: 4 additions & 8 deletions Configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -3096,11 +3096,11 @@ Note that no wrapping will happen if:
1. The comment is the start of a markdown header doc comment
2. An URL was found in the comment

- **Default value**: `false`
- **Possible values**: `true`, `false`
- **Default value**: `"off"`
- **Possible values**: `"doc"`, `"normal"`, `"all"` (alias `true`), `"off"` (alias `false`)
- **Stable**: No (tracking issue: [#3347](https://github.com/rust-lang/rustfmt/issues/3347))

#### `false` (default):
#### `"off"` (default):

```rust
// Lorem ipsum dolor sit amet, consectetur adipiscing elit,
Expand All @@ -3112,12 +3112,10 @@ Note that no wrapping will happen if:
// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

// Information on the lorem ipsum can be found at the following url: https://en.wikipedia.org/wiki/Lorem_ipsum. Its text is: lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

/// # This doc comment is a very long header (it starts with a '#'). Had it not been a header it would have been wrapped. But because it is a header, it will not be. That is because wrapping a markdown header breaks it.
struct Foo {}
```

#### `true`:
#### `"all"`:

```rust
// Lorem ipsum dolor sit amet, consectetur adipiscing elit,
Expand All @@ -3133,8 +3131,6 @@ struct Foo {}
// commodo consequat.

// Information on the lorem ipsum can be found at the following url: https://en.wikipedia.org/wiki/Lorem_ipsum. Its text is: lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

/// # This doc comment is a very long header (it starts with a '#'). Had it not been a header it would have been wrapped. But because it is a header, it will not be. That is because wrapping a markdown header breaks it.
struct Foo {}
```

Expand Down
24 changes: 24 additions & 0 deletions config_proc_macro/src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,30 @@ pub fn is_unstable_variant(attr: &syn::Attribute) -> bool {
is_attr_path(attr, "unstable_variant")
}

/// Returns the value of the first `bool` attribute in the given slice or
/// `None` if `bool` attribute is not available.
pub fn find_config_bool(attrs: &[syn::Attribute]) -> Option<bool> {
attrs.iter().filter_map(config_bool).next()
}

/// Returns a bool literal value if the given attribute is `bool`
/// attribute or `None` otherwise.
pub fn config_bool(attr: &syn::Attribute) -> Option<bool> {
match &attr.meta {
syn::Meta::NameValue(syn::MetaNameValue {
path,
value: syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Bool(lit_bool), .. }),
..
}) if path.is_ident("bool") => Some(lit_bool.value()),
_ => None,
}
}

/// Returns `true` if the given attribute is a `bool` attribute.
pub fn is_config_bool(attr: &syn::Attribute) -> bool {
is_attr_name_value(attr, "bool")
}

fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool {
match &attr.meta {
syn::Meta::NameValue(syn::MetaNameValue { path, .. }) if path.is_ident(name) => true,
Expand Down
39 changes: 36 additions & 3 deletions config_proc_macro/src/item_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fn process_variant(variant: &syn::Variant) -> TokenStream {
let metas = variant
.attrs
.iter()
.filter(|attr| !is_doc_hint(attr) && !is_config_value(attr) && !is_unstable_variant(attr));
.filter(|attr| !is_doc_hint(attr) && !is_config_value(attr) && !is_unstable_variant(attr) && !is_config_bool(attr));
let attrs = fold_quote(metas, |meta| quote!(#meta));
let syn::Variant { ident, fields, .. } = variant;
quote!(#attrs #ident #fields)
Expand Down Expand Up @@ -123,12 +123,22 @@ fn impl_from_str(ident: &syn::Ident, variants: &Variants) -> TokenStream {
let vs = variants
.iter()
.filter(|v| is_unit(v))
.map(|v| (config_value_of_variant(v), &v.ident));
let if_patterns = fold_quote(vs, |(s, v)| {
.map(|v| (config_value_of_variant(v), &v.ident, find_config_bool(&v.attrs)));
let if_patterns = fold_quote(vs, |(s, v, b)| {
let parse_bool = b.map(|b| {
let b = if b { "true" } else { "false" };
quote! {
if #b == s {
return Ok(#ident::#v);
}
}
}).unwrap_or_default();

quote! {
if #s.eq_ignore_ascii_case(s) {
return Ok(#ident::#v);
}
#parse_bool
}
});
let mut err_msg = String::from("Bad variant, expected one of:");
Expand Down Expand Up @@ -210,6 +220,27 @@ fn impl_deserialize(ident: &syn::Ident, variants: &Variants) -> TokenStream {
let supported_vs = variants.iter().filter(|v| is_unit(v));
let allowed = fold_quote(supported_vs.map(config_value_of_variant), |s| quote!(#s,));

let mut bools =
variants.iter()
.filter(|v| is_unit(v))
.filter_map(|v| Some({
let bool = find_config_bool(&v.attrs)?;
let value = config_value_of_variant(v);
quote! {
#bool => return Ok(String::from(#value)),
}
})).peekable();

let visit_bool = bools.peek().is_some().then(|| {
quote! {
fn visit_bool<E>(self, value: bool) -> Result<String, E> {
match value {
#(#bools)*
}
}
}
}).unwrap_or_default();

quote! {
impl<'de> serde::de::Deserialize<'de> for #ident {
fn deserialize<D>(d: D) -> Result<Self, D::Error>
Expand All @@ -229,7 +260,9 @@ fn impl_deserialize(ident: &syn::Ident, variants: &Variants) -> TokenStream {
fn visit_str<E>(self, value: &str) -> Result<String, E> {
Ok(String::from(value))
}
#visit_bool
}

let s = &d.deserialize_string(StringOnly::<D>(PhantomData))?;

#if_patterns
Expand Down
31 changes: 18 additions & 13 deletions src/comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use lazy_static::lazy_static;
use regex::Regex;
use rustc_span::Span;

use crate::config::Config;
use crate::config::{Config, WrapComments};
use crate::rewrite::RewriteContext;
use crate::shape::{Indent, Shape};
use crate::string::{rewrite_string, StringFormat};
Expand Down Expand Up @@ -361,12 +361,11 @@ fn identify_comment(
if !config.normalize_comments() && has_bare_lines && style.is_block_comment() {
trim_left_preserve_layout(first_group, shape.indent, config)?
} else if !config.normalize_comments()
&& !config.wrap_comments()
&& !(
// `format_code_in_doc_comments` should only take effect on doc comments,
// so we only consider it when this comment block is a doc comment block.
is_doc_comment && config.format_code_in_doc_comments()
)
&& (if is_doc_comment {
!config.wrap_comments().is_doc() && !config.format_code_in_doc_comments()
} else {
!config.wrap_comments().is_normal()
})
{
light_rewrite_comment(first_group, shape.indent, config, is_doc_comment)
} else {
Expand Down Expand Up @@ -770,7 +769,7 @@ impl<'a> CommentRewrite<'a> {
&& !self.code_block_buffer.trim().is_empty() =>
{
let mut config = self.fmt.config.clone();
config.set().wrap_comments(false);
config.set().wrap_comments(WrapComments::Off);
let comment_max_width = config
.doc_comment_code_block_width()
.min(config.max_width());
Expand Down Expand Up @@ -802,11 +801,17 @@ impl<'a> CommentRewrite<'a> {
return false;
}

let config_wrap_comments = if is_doc_comment {
self.fmt.config.wrap_comments().is_doc()
} else {
self.fmt.config.wrap_comments().is_normal()
};

self.code_block_attr = None;
self.item_block = None;
if let Some(stripped) = line.strip_prefix("```") {
self.code_block_attr = Some(CodeBlockAttribute::new(stripped))
} else if self.fmt.config.wrap_comments() {
} else if config_wrap_comments {
if let Some(ib) = ItemizedBlock::new(line) {
self.item_block = Some(ib);
return false;
Expand Down Expand Up @@ -845,7 +850,7 @@ impl<'a> CommentRewrite<'a> {
// 4) No URLS were found in the comment
// If this changes, the documentation in ../Configurations.md#wrap_comments
// should be changed accordingly.
let should_wrap_comment = self.fmt.config.wrap_comments()
let should_wrap_comment = config_wrap_comments
&& !is_markdown_header_doc_comment
&& unicode_str_width(line) > self.fmt.shape.width
&& !has_url(line)
Expand Down Expand Up @@ -1903,13 +1908,13 @@ mod test {

#[test]
#[rustfmt::skip]
fn format_doc_comments() {
fn format_comments() {
let mut wrap_normalize_config: crate::config::Config = Default::default();
wrap_normalize_config.set().wrap_comments(true);
wrap_normalize_config.set().wrap_comments(WrapComments::All);
wrap_normalize_config.set().normalize_comments(true);

let mut wrap_config: crate::config::Config = Default::default();
wrap_config.set().wrap_comments(true);
wrap_config.set().wrap_comments(WrapComments::All);

let comment = rewrite_comment(" //test",
true,
Expand Down
4 changes: 2 additions & 2 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ create_config! {
over multiple lines.";

// Comments. macros, and strings
wrap_comments: bool, false, false, "Break comments to fit on the line";
wrap_comments: WrapComments, WrapComments::Off, false, "Break comments to fit on the line";
format_code_in_doc_comments: bool, false, false, "Format the code snippet in doc comments.";
doc_comment_code_block_width: usize, 100, false, "Maximum width for code snippets in doc \
comments. No effect unless format_code_in_doc_comments = true";
Expand Down Expand Up @@ -634,7 +634,7 @@ array_width = 60
chain_width = 60
single_line_if_else_max_width = 50
single_line_let_else_max_width = 50
wrap_comments = false
wrap_comments = "Off"
format_code_in_doc_comments = false
doc_comment_code_block_width = 100
comment_width = 80
Expand Down
26 changes: 26 additions & 0 deletions src/config/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,32 @@ pub enum Verbosity {
Quiet,
}

/// Which comments to wrap
#[config_type]
#[derive(Copy)]
pub enum WrapComments {
/// Don't wrap comments
#[bool = false]
Off,
/// Wrap all kinds of comments
#[bool = true]
All,
/// Only wrap doc comments
Doc,
/// Only wrap normal comments
Normal,
}

impl WrapComments {
pub(crate) fn is_normal(self) -> bool {
matches!(self, WrapComments::All | WrapComments::Normal)
}

pub(crate) fn is_doc(self) -> bool {
matches!(self, WrapComments::All | WrapComments::Doc)
}
}

#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
pub struct WidthHeuristics {
// Maximum width of the args of a function call before falling back
Expand Down
17 changes: 17 additions & 0 deletions tests/source/configs/wrap_comments/all.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// rustfmt-wrap_comments: all
// rustfmt-max_width: 50
// Wrap comments

fn main() {
//! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
}

fn code_block() {
// ```rust
// let x = 3;
//
// println!("x = {}", x);
// ```
}
17 changes: 17 additions & 0 deletions tests/source/configs/wrap_comments/doc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// rustfmt-wrap_comments: doc
// rustfmt-max_width: 50
/// Wrap comments
fn main() {
//! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
}

fn code_block() {
// ```rust
// let x = 3;
//
// println!("x = {}", x);
// ```
}
10 changes: 10 additions & 0 deletions tests/source/configs/wrap_comments/false.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,15 @@
// Wrap comments

fn main() {
//! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
}

fn code_block() {
//! ```rust
//! let x = 3;
//!
//! println!("x = {}", x);
//! ```
}
18 changes: 18 additions & 0 deletions tests/source/configs/wrap_comments/normal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// rustfmt-wrap_comments: normal
// rustfmt-max_width: 50
// rustfmt-error_on_line_overflow: false
// Wrap comments

fn main() {
//! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
}

fn code_block() {
//! ```rust
//! let x = 3;
//!
//! println!("x = {}", x);
//! ```
}
18 changes: 18 additions & 0 deletions tests/source/configs/wrap_comments/off.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// rustfmt-wrap_comments: off
// rustfmt-max_width: 50
// rustfmt-error_on_line_overflow: false
// Wrap comments

fn main() {
//! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
}

fn code_block() {
//! ```rust
//! let x = 3;
//!
//! println!("x = {}", x);
//! ```
}
2 changes: 2 additions & 0 deletions tests/source/configs/wrap_comments/true.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// Wrap comments

fn main() {
//! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
}

Expand Down
27 changes: 27 additions & 0 deletions tests/target/configs/wrap_comments/all.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// rustfmt-wrap_comments: all
// rustfmt-max_width: 50
// Wrap comments

fn main() {
//! Lorem ipsum dolor sit amet, consectetur
//! adipiscing elit, sed do eiusmod tempor
//! incididunt ut labore et dolore magna
//! aliqua. Ut enim ad minim veniam, quis
//! nostrud exercitation ullamco laboris nisi
//! ut aliquip ex ea commodo consequat.
// Lorem ipsum dolor sit amet, consectetur
// adipiscing elit, sed do eiusmod tempor
// incididunt ut labore et dolore magna
// aliqua. Ut enim ad minim veniam, quis
// nostrud exercitation ullamco laboris nisi
// ut aliquip ex ea commodo consequat.
}

fn code_block() {
// ```rust
// let x = 3;
//
// println!("x = {}", x);
// ```
}
Loading

0 comments on commit 4c0eba4

Please sign in to comment.