Skip to content

Fix normalisation of multiline doc attributes #3548

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

Merged
merged 8 commits into from
May 20, 2019
Merged
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
11 changes: 6 additions & 5 deletions src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use syntax::ast;
use syntax::source_map::{BytePos, Span, DUMMY_SP};

use self::doc_comment::DocCommentFormatter;
use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle};
use crate::config::lists::*;
use crate::config::IndentStyle;
Expand All @@ -14,6 +15,8 @@ use crate::shape::Shape;
use crate::types::{rewrite_path, PathContext};
use crate::utils::{count_newlines, mk_sp};

mod doc_comment;

/// Returns attributes on the given statement.
pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] {
match stmt.node {
Expand Down Expand Up @@ -330,11 +333,9 @@ impl Rewrite for ast::Attribute {
ast::AttrStyle::Outer => CommentStyle::TripleSlash,
};

// Remove possible whitespace from the `CommentStyle::opener()` so that
// the literal itself has control over the comment's leading spaces.
let opener = comment_style.opener().trim_end();

let doc_comment = format!("{}{}", opener, literal);
let doc_comment_formatter =
DocCommentFormatter::new(literal.as_str().get(), comment_style);
let doc_comment = format!("{}", doc_comment_formatter);
return rewrite_doc_comment(
&doc_comment,
shape.comment(context.config),
Expand Down
77 changes: 77 additions & 0 deletions src/attr/doc_comment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use crate::comment::CommentStyle;
use std::fmt::{self, Display};

/// Formats a string as a doc comment using the given [`CommentStyle`].
#[derive(new)]
pub(super) struct DocCommentFormatter<'a> {
literal: &'a str,
style: CommentStyle<'a>,
}

impl Display for DocCommentFormatter<'_> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let opener = self.style.opener().trim_end();
let mut lines = self.literal.lines().peekable();
while let Some(line) = lines.next() {
let is_last_line = lines.peek().is_none();
if is_last_line {
write!(formatter, "{}{}", opener, line)?;
} else {
writeln!(formatter, "{}{}", opener, line)?;
}
}
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn literal_controls_leading_spaces() {
test_doc_comment_is_formatted_correctly(
" Lorem ipsum",
"/// Lorem ipsum",
CommentStyle::TripleSlash,
);
}

#[test]
fn single_line_doc_comment_is_formatted_correctly() {
test_doc_comment_is_formatted_correctly(
"Lorem ipsum",
"///Lorem ipsum",
CommentStyle::TripleSlash,
);
}

#[test]
fn multi_line_doc_comment_is_formatted_correctly() {
test_doc_comment_is_formatted_correctly(
"Lorem ipsum\nDolor sit amet",
"///Lorem ipsum\n///Dolor sit amet",
CommentStyle::TripleSlash,
);
}

#[test]
fn whitespace_within_lines_is_preserved() {
test_doc_comment_is_formatted_correctly(
" Lorem ipsum \n Dolor sit amet ",
"/// Lorem ipsum \n/// Dolor sit amet ",
CommentStyle::TripleSlash,
);
}

fn test_doc_comment_is_formatted_correctly(
literal: &str,
expected_comment: &str,
style: CommentStyle<'_>,
) {
assert_eq!(
expected_comment,
format!("{}", DocCommentFormatter::new(&literal, style))
);
}
}
7 changes: 7 additions & 0 deletions tests/source/normalize_multiline_doc_attribute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// rustfmt-unstable: true
// rustfmt-normalize_doc_attributes: true

#[doc = "This comment
is split
on multiple lines"]
fn foo() {}
7 changes: 7 additions & 0 deletions tests/target/normalize_multiline_doc_attribute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// rustfmt-unstable: true
// rustfmt-normalize_doc_attributes: true

///This comment
///is split
///on multiple lines
fn foo() {}