rustfmt_nightly/attr/
doc_comment.rs

1use crate::comment::CommentStyle;
2use std::fmt::{self, Display};
3
4/// Formats a string as a doc comment using the given [`CommentStyle`].
5pub(super) struct DocCommentFormatter<'a> {
6    literal: &'a str,
7    style: CommentStyle<'a>,
8}
9
10impl<'a> DocCommentFormatter<'a> {
11    pub(super) const fn new(literal: &'a str, style: CommentStyle<'a>) -> Self {
12        Self { literal, style }
13    }
14}
15
16impl Display for DocCommentFormatter<'_> {
17    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
18        let opener = self.style.opener().trim_end();
19        let mut lines = self.literal.lines().peekable();
20
21        // Handle `#[doc = ""]`.
22        if lines.peek().is_none() {
23            return write!(formatter, "{opener}");
24        }
25
26        while let Some(line) = lines.next() {
27            let is_last_line = lines.peek().is_none();
28            if is_last_line {
29                write!(formatter, "{opener}{line}")?;
30            } else {
31                writeln!(formatter, "{opener}{line}")?;
32            }
33        }
34        Ok(())
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn literal_controls_leading_spaces() {
44        test_doc_comment_is_formatted_correctly(
45            "    Lorem ipsum",
46            "///    Lorem ipsum",
47            CommentStyle::TripleSlash,
48        );
49    }
50
51    #[test]
52    fn single_line_doc_comment_is_formatted_correctly() {
53        test_doc_comment_is_formatted_correctly(
54            "Lorem ipsum",
55            "///Lorem ipsum",
56            CommentStyle::TripleSlash,
57        );
58    }
59
60    #[test]
61    fn multi_line_doc_comment_is_formatted_correctly() {
62        test_doc_comment_is_formatted_correctly(
63            "Lorem ipsum\nDolor sit amet",
64            "///Lorem ipsum\n///Dolor sit amet",
65            CommentStyle::TripleSlash,
66        );
67    }
68
69    #[test]
70    fn whitespace_within_lines_is_preserved() {
71        test_doc_comment_is_formatted_correctly(
72            " Lorem ipsum \n Dolor sit amet ",
73            "/// Lorem ipsum \n/// Dolor sit amet ",
74            CommentStyle::TripleSlash,
75        );
76    }
77
78    fn test_doc_comment_is_formatted_correctly(
79        literal: &str,
80        expected_comment: &str,
81        style: CommentStyle<'_>,
82    ) {
83        assert_eq!(
84            expected_comment,
85            format!("{}", DocCommentFormatter::new(literal, style))
86        );
87    }
88}