<commit_before>use crate::comment::CommentStyle;
use std::fmt::{self, Display};
use syntax_pos::symbol::Symbol;

pub(super) struct DocCommentFormatter<'a> {
    literal: &'a Symbol,
    style: CommentStyle<'a>,
}

impl<'a> DocCommentFormatter<'a> {
    pub(super) fn new(literal: &'a Symbol, 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 literal_as_str = self.literal.as_str().get();
        let line_count = literal_as_str.lines().count();
        let last_line_index = line_count - 1;
        let lines = literal_as_str.lines().enumerate();

        for (index, line) in lines {
            if index == last_line_index {
                write!(formatter, "{}{}", opener, line)?;
            } else {
                writeln!(formatter, "{}{}", opener, line)?;
            }
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use syntax_pos::{Globals, GLOBALS};

    #[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,<commit_msg>Use peek() instead of checking indexes<commit_after>use crate::comment::CommentStyle;
use std::fmt::{self, Display};
use syntax_pos::symbol::Symbol;

pub(super) struct DocCommentFormatter<'a> {
    literal: &'a Symbol,
    style: CommentStyle<'a>,
}

impl<'a> DocCommentFormatter<'a> {
    pub(super) fn new(literal: &'a Symbol, 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 literal_as_str = self.literal.as_str().get();

        let mut lines = literal_as_str.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::*;
    use syntax_pos::{Globals, GLOBALS};

    #[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,
{'fraction_non_alphanumeric': 0.14433656957928803, 'fraction_numerical': 0.00032362459546925567, 'mean_word_length': 2.4344444444444444, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2064172', 'n_tokens_mistral': 979, 'n_tokens_neox': 979, 'n_words': 191}