| use crate::comment::CommentStyle; |
| use std::fmt::{self, Display}; |
| |
| /// Formats a string as a doc comment using the given [`CommentStyle`]. |
| pub(super) struct DocCommentFormatter<'a> { |
| literal: &'a str, |
| style: CommentStyle<'a>, |
| } |
| |
| impl<'a> DocCommentFormatter<'a> { |
| pub(super) const fn new(literal: &'a str, style: CommentStyle<'a>) -> Self { |
| Self { literal, style } |
| } |
| } |
| |
| 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(); |
| |
| // Handle `#[doc = ""]`. |
| if lines.peek().is_none() { |
| return write!(formatter, "{opener}"); |
| } |
| |
| 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)) |
| ); |
| } |
| } |