|  | 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(); | 
|  |  | 
|  | // 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)) | 
|  | ); | 
|  | } | 
|  | } |