Skip to content

Commit e9b5ca0

Browse files
committed
Partition wrap_comments into normal or doc settings
1 parent ead0fc9 commit e9b5ca0

File tree

19 files changed

+301
-28
lines changed

19 files changed

+301
-28
lines changed

Diff for: Configurations.md

+4-8
Original file line numberDiff line numberDiff line change
@@ -3096,11 +3096,11 @@ Note that no wrapping will happen if:
30963096
1. The comment is the start of a markdown header doc comment
30973097
2. An URL was found in the comment
30983098

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

3103-
#### `false` (default):
3103+
#### `"off"` (default):
31043104

31053105
```rust
31063106
// Lorem ipsum dolor sit amet, consectetur adipiscing elit,
@@ -3112,12 +3112,10 @@ Note that no wrapping will happen if:
31123112
// 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.
31133113

31143114
// 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.
3115-
3116-
/// # 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.
31173115
struct Foo {}
31183116
```
31193117

3120-
#### `true`:
3118+
#### `"all"`:
31213119

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

31353133
// 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.
3136-
3137-
/// # 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.
31383134
struct Foo {}
31393135
```
31403136

Diff for: config_proc_macro/src/attrs.rs

+24
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,30 @@ pub fn is_unstable_variant(attr: &syn::Attribute) -> bool {
5050
is_attr_path(attr, "unstable_variant")
5151
}
5252

53+
/// Returns the value of the first `bool` attribute in the given slice or
54+
/// `None` if `bool` attribute is not available.
55+
pub fn find_config_bool(attrs: &[syn::Attribute]) -> Option<bool> {
56+
attrs.iter().filter_map(config_bool).next()
57+
}
58+
59+
/// Returns a bool literal value if the given attribute is `bool`
60+
/// attribute or `None` otherwise.
61+
pub fn config_bool(attr: &syn::Attribute) -> Option<bool> {
62+
match &attr.meta {
63+
syn::Meta::NameValue(syn::MetaNameValue {
64+
path,
65+
value: syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Bool(lit_bool), .. }),
66+
..
67+
}) if path.is_ident("bool") => Some(lit_bool.value()),
68+
_ => None,
69+
}
70+
}
71+
72+
/// Returns `true` if the given attribute is a `bool` attribute.
73+
pub fn is_config_bool(attr: &syn::Attribute) -> bool {
74+
is_attr_name_value(attr, "bool")
75+
}
76+
5377
fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool {
5478
match &attr.meta {
5579
syn::Meta::NameValue(syn::MetaNameValue { path, .. }) if path.is_ident(name) => true,

Diff for: config_proc_macro/src/item_enum.rs

+36-3
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ fn process_variant(variant: &syn::Variant) -> TokenStream {
4848
let metas = variant
4949
.attrs
5050
.iter()
51-
.filter(|attr| !is_doc_hint(attr) && !is_config_value(attr) && !is_unstable_variant(attr));
51+
.filter(|attr| !is_doc_hint(attr) && !is_config_value(attr) && !is_unstable_variant(attr) && !is_config_bool(attr));
5252
let attrs = fold_quote(metas, |meta| quote!(#meta));
5353
let syn::Variant { ident, fields, .. } = variant;
5454
quote!(#attrs #ident #fields)
@@ -123,12 +123,22 @@ fn impl_from_str(ident: &syn::Ident, variants: &Variants) -> TokenStream {
123123
let vs = variants
124124
.iter()
125125
.filter(|v| is_unit(v))
126-
.map(|v| (config_value_of_variant(v), &v.ident));
127-
let if_patterns = fold_quote(vs, |(s, v)| {
126+
.map(|v| (config_value_of_variant(v), &v.ident, find_config_bool(&v.attrs)));
127+
let if_patterns = fold_quote(vs, |(s, v, b)| {
128+
let parse_bool = b.map(|b| {
129+
let b = if b { "true" } else { "false" };
130+
quote! {
131+
if #b == s {
132+
return Ok(#ident::#v);
133+
}
134+
}
135+
}).unwrap_or_default();
136+
128137
quote! {
129138
if #s.eq_ignore_ascii_case(s) {
130139
return Ok(#ident::#v);
131140
}
141+
#parse_bool
132142
}
133143
});
134144
let mut err_msg = String::from("Bad variant, expected one of:");
@@ -210,6 +220,27 @@ fn impl_deserialize(ident: &syn::Ident, variants: &Variants) -> TokenStream {
210220
let supported_vs = variants.iter().filter(|v| is_unit(v));
211221
let allowed = fold_quote(supported_vs.map(config_value_of_variant), |s| quote!(#s,));
212222

223+
let mut bools =
224+
variants.iter()
225+
.filter(|v| is_unit(v))
226+
.filter_map(|v| Some({
227+
let bool = find_config_bool(&v.attrs)?;
228+
let value = config_value_of_variant(v);
229+
quote! {
230+
#bool => return Ok(String::from(#value)),
231+
}
232+
})).peekable();
233+
234+
let visit_bool = bools.peek().is_some().then(|| {
235+
quote! {
236+
fn visit_bool<E>(self, value: bool) -> Result<String, E> {
237+
match value {
238+
#(#bools)*
239+
}
240+
}
241+
}
242+
}).unwrap_or_default();
243+
213244
quote! {
214245
impl<'de> serde::de::Deserialize<'de> for #ident {
215246
fn deserialize<D>(d: D) -> Result<Self, D::Error>
@@ -229,7 +260,9 @@ fn impl_deserialize(ident: &syn::Ident, variants: &Variants) -> TokenStream {
229260
fn visit_str<E>(self, value: &str) -> Result<String, E> {
230261
Ok(String::from(value))
231262
}
263+
#visit_bool
232264
}
265+
233266
let s = &d.deserialize_string(StringOnly::<D>(PhantomData))?;
234267

235268
#if_patterns

Diff for: src/comment.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use lazy_static::lazy_static;
77
use regex::Regex;
88
use rustc_span::Span;
99

10-
use crate::config::Config;
10+
use crate::config::{Config, WrapComments};
1111
use crate::rewrite::RewriteContext;
1212
use crate::shape::{Indent, Shape};
1313
use crate::string::{rewrite_string, StringFormat};
@@ -361,12 +361,11 @@ fn identify_comment(
361361
if !config.normalize_comments() && has_bare_lines && style.is_block_comment() {
362362
trim_left_preserve_layout(first_group, shape.indent, config)?
363363
} else if !config.normalize_comments()
364-
&& !config.wrap_comments()
365-
&& !(
366-
// `format_code_in_doc_comments` should only take effect on doc comments,
367-
// so we only consider it when this comment block is a doc comment block.
368-
is_doc_comment && config.format_code_in_doc_comments()
369-
)
364+
&& (if is_doc_comment {
365+
!config.wrap_comments().is_doc() && !config.format_code_in_doc_comments()
366+
} else {
367+
!config.wrap_comments().is_normal()
368+
})
370369
{
371370
light_rewrite_comment(first_group, shape.indent, config, is_doc_comment)
372371
} else {
@@ -770,7 +769,7 @@ impl<'a> CommentRewrite<'a> {
770769
&& !self.code_block_buffer.trim().is_empty() =>
771770
{
772771
let mut config = self.fmt.config.clone();
773-
config.set().wrap_comments(false);
772+
config.set().wrap_comments(WrapComments::Off);
774773
let comment_max_width = config
775774
.doc_comment_code_block_width()
776775
.min(config.max_width());
@@ -802,11 +801,17 @@ impl<'a> CommentRewrite<'a> {
802801
return false;
803802
}
804803

804+
let config_wrap_comments = if is_doc_comment {
805+
self.fmt.config.wrap_comments().is_doc()
806+
} else {
807+
self.fmt.config.wrap_comments().is_normal()
808+
};
809+
805810
self.code_block_attr = None;
806811
self.item_block = None;
807812
if let Some(stripped) = line.strip_prefix("```") {
808813
self.code_block_attr = Some(CodeBlockAttribute::new(stripped))
809-
} else if self.fmt.config.wrap_comments() {
814+
} else if config_wrap_comments {
810815
if let Some(ib) = ItemizedBlock::new(line) {
811816
self.item_block = Some(ib);
812817
return false;
@@ -845,7 +850,7 @@ impl<'a> CommentRewrite<'a> {
845850
// 4) No URLS were found in the comment
846851
// If this changes, the documentation in ../Configurations.md#wrap_comments
847852
// should be changed accordingly.
848-
let should_wrap_comment = self.fmt.config.wrap_comments()
853+
let should_wrap_comment = config_wrap_comments
849854
&& !is_markdown_header_doc_comment
850855
&& unicode_str_width(line) > self.fmt.shape.width
851856
&& !has_url(line)
@@ -1903,13 +1908,13 @@ mod test {
19031908

19041909
#[test]
19051910
#[rustfmt::skip]
1906-
fn format_doc_comments() {
1911+
fn format_comments() {
19071912
let mut wrap_normalize_config: crate::config::Config = Default::default();
1908-
wrap_normalize_config.set().wrap_comments(true);
1913+
wrap_normalize_config.set().wrap_comments(WrapComments::All);
19091914
wrap_normalize_config.set().normalize_comments(true);
19101915

19111916
let mut wrap_config: crate::config::Config = Default::default();
1912-
wrap_config.set().wrap_comments(true);
1917+
wrap_config.set().wrap_comments(WrapComments::All);
19131918

19141919
let comment = rewrite_comment(" //test",
19151920
true,

Diff for: src/config/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ create_config! {
6363
over multiple lines.";
6464

6565
// Comments. macros, and strings
66-
wrap_comments: bool, false, false, "Break comments to fit on the line";
66+
wrap_comments: WrapComments, WrapComments::Off, false, "Break comments to fit on the line";
6767
format_code_in_doc_comments: bool, false, false, "Format the code snippet in doc comments.";
6868
doc_comment_code_block_width: usize, 100, false, "Maximum width for code snippets in doc \
6969
comments. No effect unless format_code_in_doc_comments = true";
@@ -634,7 +634,7 @@ array_width = 60
634634
chain_width = 60
635635
single_line_if_else_max_width = 50
636636
single_line_let_else_max_width = 50
637-
wrap_comments = false
637+
wrap_comments = "Off"
638638
format_code_in_doc_comments = false
639639
doc_comment_code_block_width = 100
640640
comment_width = 80

Diff for: src/config/options.rs

+26
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,32 @@ pub enum Verbosity {
216216
Quiet,
217217
}
218218

219+
/// Which comments to wrap
220+
#[config_type]
221+
#[derive(Copy)]
222+
pub enum WrapComments {
223+
/// Don't wrap comments
224+
#[bool = false]
225+
Off,
226+
/// Wrap all kinds of comments
227+
#[bool = true]
228+
All,
229+
/// Only wrap doc comments
230+
Doc,
231+
/// Only wrap normal comments
232+
Normal,
233+
}
234+
235+
impl WrapComments {
236+
pub(crate) fn is_normal(self) -> bool {
237+
matches!(self, WrapComments::All | WrapComments::Normal)
238+
}
239+
240+
pub(crate) fn is_doc(self) -> bool {
241+
matches!(self, WrapComments::All | WrapComments::Doc)
242+
}
243+
}
244+
219245
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
220246
pub struct WidthHeuristics {
221247
// Maximum width of the args of a function call before falling back

Diff for: src/test/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ fn verify_config_used(path: &Path, config_name: &str) {
134134
filebuf
135135
.lines()
136136
.map(Result::unwrap)
137-
.take_while(|l| l.starts_with("//"))
138-
.any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))),
137+
.take_while(|l| dbg!(l).starts_with("//"))
138+
.any(|l| l.starts_with(&dbg!(format!("// rustfmt-{}", config_name)))),
139139
"config option file {} does not contain expected config name",
140140
path.display()
141141
);

Diff for: tests/source/configs/wrap_comments/all.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// rustfmt-wrap_comments: all
2+
// rustfmt-max_width: 50
3+
// Wrap comments
4+
5+
fn main() {
6+
//! 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.
7+
8+
// 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.
9+
}
10+
11+
fn code_block() {
12+
// ```rust
13+
// let x = 3;
14+
//
15+
// println!("x = {}", x);
16+
// ```
17+
}

Diff for: tests/source/configs/wrap_comments/doc.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// rustfmt-wrap_comments: doc
2+
// rustfmt-max_width: 50
3+
/// Wrap comments
4+
5+
fn main() {
6+
//! 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.
7+
8+
// 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.
9+
}
10+
11+
fn code_block() {
12+
// ```rust
13+
// let x = 3;
14+
//
15+
// println!("x = {}", x);
16+
// ```
17+
}

Diff for: tests/source/configs/wrap_comments/false.rs

+10
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,15 @@
44
// Wrap comments
55

66
fn main() {
7+
//! 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.
8+
79
// 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.
810
}
11+
12+
fn code_block() {
13+
//! ```rust
14+
//! let x = 3;
15+
//!
16+
//! println!("x = {}", x);
17+
//! ```
18+
}

Diff for: tests/source/configs/wrap_comments/normal.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// rustfmt-wrap_comments: normal
2+
// rustfmt-max_width: 50
3+
// rustfmt-error_on_line_overflow: false
4+
// Wrap comments
5+
6+
fn main() {
7+
//! 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.
8+
9+
// 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.
10+
}
11+
12+
fn code_block() {
13+
//! ```rust
14+
//! let x = 3;
15+
//!
16+
//! println!("x = {}", x);
17+
//! ```
18+
}

Diff for: tests/source/configs/wrap_comments/off.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// rustfmt-wrap_comments: off
2+
// rustfmt-max_width: 50
3+
// rustfmt-error_on_line_overflow: false
4+
// Wrap comments
5+
6+
fn main() {
7+
//! 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.
8+
9+
// 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.
10+
}
11+
12+
fn code_block() {
13+
//! ```rust
14+
//! let x = 3;
15+
//!
16+
//! println!("x = {}", x);
17+
//! ```
18+
}

Diff for: tests/source/configs/wrap_comments/true.rs

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// Wrap comments
44

55
fn main() {
6+
//! 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.
7+
68
// 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.
79
}
810

0 commit comments

Comments
 (0)