use ruff_formatter::{format_args, write}; use ruff_python_ast::{Stmt, StmtWhile}; use ruff_text_size::Ranged; use crate::expression::maybe_parenthesize_expression; use crate::expression::parentheses::Parenthesize; use crate::prelude::*; use crate::statement::clause::{clause_body, clause_header, ClauseHeader, ElseClause}; use crate::statement::suite::SuiteKind; #[derive(Default)] pub struct FormatStmtWhile; impl FormatNodeRule for FormatStmtWhile { fn fmt_fields(&self, item: &StmtWhile, f: &mut PyFormatter) -> FormatResult<()> { let StmtWhile { range: _, test, body, orelse, } = item; let comments = f.context().comments().clone(); let dangling_comments = comments.dangling(item); let body_start = body.first().map_or(test.end(), Stmt::start); let or_else_comments_start = dangling_comments.partition_point(|comment| comment.end() < body_start); let (trailing_condition_comments, or_else_comments) = dangling_comments.split_at(or_else_comments_start); write!( f, [ clause_header( ClauseHeader::While(item), trailing_condition_comments, &format_args![ token("while"), space(), maybe_parenthesize_expression(test, item, Parenthesize::IfBreaks), ] ), clause_body( body, SuiteKind::other(orelse.is_empty()), trailing_condition_comments ), ] )?; if !orelse.is_empty() { // Split between leading comments before the `else` keyword and end of line comments at the end of // the `else:` line. let trailing_start = or_else_comments.partition_point(|comment| comment.line_position().is_own_line()); let (leading, trailing) = or_else_comments.split_at(trailing_start); write!( f, [ clause_header( ClauseHeader::OrElse(ElseClause::While(item)), trailing, &token("else") ) .with_leading_comments(leading, body.last()), clause_body(orelse, SuiteKind::other(true), trailing), ] )?; } Ok(()) } }