Merge pull request #3548 from bash/normalize-multiline-doc-attributes

Fix normalisation of multiline doc attributes
This commit is contained in:
Seiichi Uchida 2019-05-20 16:46:52 +09:00 committed by GitHub
commit 0482ac88f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 97 additions and 5 deletions

View File

@ -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;
@ -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 {
@ -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),

77
src/attr/doc_comment.rs Normal file
View File

@ -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))
);
}
}

View File

@ -0,0 +1,7 @@
// rustfmt-unstable: true
// rustfmt-normalize_doc_attributes: true
#[doc = "This comment
is split
on multiple lines"]
fn foo() {}

View File

@ -0,0 +1,7 @@
// rustfmt-unstable: true
// rustfmt-normalize_doc_attributes: true
///This comment
///is split
///on multiple lines
fn foo() {}