Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partition wrap_comments into normal or doc settings #5943

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 65 additions & 9 deletions Configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -3096,36 +3096,88 @@ 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**: `"Off"` (alias `false`), `"All"` (alias `true`), `"Doc"`, `"Normal"`
- **Stable**: No (tracking issue: [#3347](https://github.com/rust-lang/rustfmt/issues/3347))

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

Can also be specified as `wrap_comments = false`.

```rust
// 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 comment looks like a very long header (it starts with a '#'). Had it been a doc comment it would not have been wrapped, because wrapping a markdown header breaks it. But because it is a normal comment, it will be.

// 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.
///
/// 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.
struct Foo {}
```

#### `true`:
#### `"All"`:

Can also be specified as `wrap_comments = true`.

```rust
// # This comment looks like a very long header (it starts
// with a '#'). Had it been a doc comment it would not have
// been wrapped, because wrapping a markdown header breaks
// it. But because it is a normal comment, it will be.

// 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.
///
/// 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.
struct Foo {}
```

#### `"Doc"`:

```rust
// # This comment looks like a very long header (it starts with a '#'). Had it been a doc comment it would not have been wrapped, because wrapping a markdown header breaks it. But because it is a normal comment, it will be.

// 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.
///
/// 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.
struct Foo {}
```

#### `"Normal"`:

```rust
// # This comment looks like a very long header (it starts
// with a '#'). Had it been a doc comment it would not have
// been wrapped, because wrapping a markdown header breaks
// it. But because it is a normal comment, it will be.

// 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
Expand All @@ -3135,6 +3187,10 @@ struct Foo {}
// 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.
///
/// 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.
struct Foo {}
```

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
7 changes: 7 additions & 0 deletions src/config/config_type.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::config::file_lines::FileLines;
use crate::config::macro_names::MacroSelectors;
use crate::config::options::{IgnoreList, WidthHeuristics};
use crate::config::WrapComments;

/// Trait for types that can be used in `Config`.
pub(crate) trait ConfigType: Sized {
Expand Down Expand Up @@ -65,6 +66,12 @@ impl ConfigType for IgnoreList {
}
}

impl ConfigType for WrapComments {
fn doc_hint() -> String {
"[ Off (false) | All (true) | Doc | Normal ]".to_owned()
}
}

macro_rules! create_config {
// Options passed into the macro.
//
Expand Down
6 changes: 4 additions & 2 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub use crate::config::lists::*;
pub use crate::config::macro_names::{MacroSelector, MacroSelectors};
#[allow(unreachable_pub)]
pub use crate::config::options::*;
pub(crate) use crate::config::wrap_comments::WrapComments;

#[macro_use]
pub(crate) mod config_type;
Expand All @@ -27,6 +28,7 @@ pub(crate) mod file_lines;
pub(crate) mod lists;
pub(crate) mod macro_names;
pub(crate) mod style_edition;
mod wrap_comments;

// This macro defines configuration options used in rustfmt. Each option
// is defined as follows:
Expand Down Expand Up @@ -63,7 +65,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 +636,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
84 changes: 84 additions & 0 deletions src/config/wrap_comments.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use std::fmt;

/// Which comments to wrap
#[derive(Copy, Clone, Debug, Eq, PartialEq, serde::Serialize)]
pub enum WrapComments {
/// Don't wrap comments
Off,
/// Wrap all kinds of comments
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)
}
}

impl fmt::Display for WrapComments {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
WrapComments::Off => f.write_str("Off"),
WrapComments::All => f.write_str("All"),
WrapComments::Doc => f.write_str("Doc"),
WrapComments::Normal => f.write_str("Normal"),
}
}
}

impl std::str::FromStr for WrapComments {
type Err = &'static str;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"off" | "false" => Ok(WrapComments::Off),
"all" | "true" => Ok(WrapComments::All),
"doc" => Ok(WrapComments::Doc),
"normal" => Ok(WrapComments::Normal),
_ => {
Err("Bad variant, expected one of: `Off`, `false`, `All`, `true`, `Doc`, `Normal`")
}
}
}
}

impl<'de> serde::de::Deserialize<'de> for WrapComments {
fn deserialize<D>(d: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;

struct StringOrBoolVisitor;

impl<'de> serde::de::Visitor<'de> for StringOrBoolVisitor {
type Value = String;

fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("string")
}

fn visit_str<E>(self, value: &str) -> Result<String, E> {
Ok(String::from(value))
}

fn visit_bool<E>(self, value: bool) -> Result<String, E> {
Ok(value.to_string())
}
}

let s = d.deserialize_string(StringOrBoolVisitor)?;
s.parse().map_err(|_| {
static ALLOWED: &'static [&str] = &["Off", "false", "All", "true", "Doc", "Normal"];
D::Error::unknown_variant(&s, ALLOWED)
})
}
}
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);
//! ```
}
Loading
Loading