parol-ls 4.4.0

Language server for parol parser generator
use super::super::{
    comments::Comments,
    context::{FormatterContext, semicolon_starts_on_new_line},
    line::Line,
};
use super::helpers::{
    comment_opts_force_single_newline, comment_opts_left, format_comments_before_token,
};
use super::traits::Fmt;
use crate::parol_ls_grammar_trait::{Production, ProductionLHS};

pub(super) fn format_production_with_context(
    production: &Production,
    context: &FormatterContext<'_>,
    comments: Comments,
) -> (String, Comments) {
    let (production_l_h_s, comments) =
        format_production_lhs_with_context(&production.production_l_h_s, context, comments);
    let (mut alternations_str, comments) = production.alternations.txt(context.policy(), comments);
    let (mut comments_before_semicolon, comments) = format_comments_before_token(
        comments,
        &production.semicolon,
        &comment_opts_left(context.policy()),
    );

    alternations_str = alternations_str.trim_end().to_owned();
    let context = context.with_semicolon_starts_on_new_line(semicolon_starts_on_new_line(
        context.policy(),
        &comments_before_semicolon,
    ));

    let mut semi_nl_opt = "";
    if context.semicolon_starts_on_new_line() {
        if Line::ends_with_nl(&comments_before_semicolon) {
            comments_before_semicolon.clone_from(&comments_before_semicolon.trim_end().to_owned());
        }
        semi_nl_opt = "\n    ";
    }

    let prod_nl_opt = if context.empty_line_after_prod() {
        "\n"
    } else {
        ""
    };

    (
        format!(
            "{} {}{}{}{}{}",
            production_l_h_s,
            alternations_str,
            comments_before_semicolon,
            semi_nl_opt,
            production.semicolon,
            prod_nl_opt,
        ),
        comments,
    )
}

pub(super) fn format_production_lhs_with_context(
    production_lhs: &ProductionLHS,
    context: &FormatterContext<'_>,
    comments: Comments,
) -> (String, Comments) {
    let (comments_before_non_terminal, comments) = format_comments_before_token(
        comments,
        &production_lhs.identifier.identifier,
        &comment_opts_force_single_newline(context.policy()),
    );
    let (comments_before_colon, comments) = format_comments_before_token(
        comments,
        &production_lhs.colon,
        &comment_opts_left(context.policy()),
    );

    if production_lhs.identifier.identifier.text().len() + comments_before_colon.len() < 5 {
        let padding = " ".repeat(4 - production_lhs.identifier.identifier.text().len());
        (
            format!(
                "\n{}{}{}{}{}",
                comments_before_non_terminal,
                production_lhs.identifier.identifier,
                padding,
                comments_before_colon,
                production_lhs.colon
            ),
            comments,
        )
    } else {
        (
            format!(
                "\n{}{}{}\n    {}",
                comments_before_non_terminal,
                production_lhs.identifier.identifier,
                comments_before_colon,
                production_lhs.colon
            ),
            comments,
        )
    }
}