use rustpython_parser::ast::Constant; use ruff_formatter::prelude::*; use ruff_formatter::write; use ruff_text_size::TextSize; use crate::context::ASTFormatContext; use crate::cst::{Pattern, PatternKind}; use crate::shared_traits::AsFormat; pub struct FormatPattern<'a> { item: &'a Pattern, } impl AsFormat for Pattern { type Format<'a> = FormatPattern<'a>; fn format(&self) -> Self::Format<'_> { FormatPattern { item: self } } } impl Format for FormatPattern<'_> { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { let pattern = self.item; match &pattern.node { PatternKind::MatchValue { value } => { write!(f, [value.format()])?; } PatternKind::MatchSingleton { value } => match value { Constant::None => write!(f, [text("None")])?, Constant::Bool(value) => { if *value { write!(f, [text("True")])?; } else { write!(f, [text("False")])?; } } _ => unreachable!("singleton pattern must be None or bool"), }, PatternKind::MatchSequence { patterns } => { write!(f, [text("[")])?; if let Some(pattern) = patterns.first() { write!(f, [pattern.format()])?; } for pattern in patterns.iter().skip(1) { write!(f, [text(","), space(), pattern.format()])?; } write!(f, [text("]")])?; } PatternKind::MatchMapping { keys, patterns, rest, } => { write!(f, [text("{")])?; if let Some(pattern) = patterns.first() { write!(f, [keys[0].format(), text(":"), space(), pattern.format()])?; } for (key, pattern) in keys.iter().skip(1).zip(patterns.iter().skip(1)) { write!( f, [ text(","), space(), key.format(), text(":"), space(), pattern.format() ] )?; } if let Some(rest) = &rest { write!( f, [ text(","), space(), text("**"), space(), dynamic_text(rest, TextSize::default()) ] )?; } write!(f, [text("}")])?; } PatternKind::MatchClass { cls, patterns, kwd_attrs, kwd_patterns, } => { write!(f, [cls.format()])?; if !patterns.is_empty() { write!(f, [text("(")])?; if let Some(pattern) = patterns.first() { write!(f, [pattern.format()])?; } for pattern in patterns.iter().skip(1) { write!(f, [text(","), space(), pattern.format()])?; } write!(f, [text(")")])?; } if !kwd_attrs.is_empty() { write!(f, [text("(")])?; if let Some(attr) = kwd_attrs.first() { write!(f, [dynamic_text(attr, TextSize::default())])?; } for attr in kwd_attrs.iter().skip(1) { write!( f, [text(","), space(), dynamic_text(attr, TextSize::default())] )?; } write!(f, [text(")")])?; } if !kwd_patterns.is_empty() { write!(f, [text("(")])?; if let Some(pattern) = kwd_patterns.first() { write!(f, [pattern.format()])?; } for pattern in kwd_patterns.iter().skip(1) { write!(f, [text(","), space(), pattern.format()])?; } write!(f, [text(")")])?; } } PatternKind::MatchStar { name } => { if let Some(name) = name { write!(f, [text("*"), dynamic_text(name, TextSize::default())])?; } else { write!(f, [text("*_")])?; } } PatternKind::MatchAs { pattern, name } => { if let Some(pattern) = &pattern { write!(f, [pattern.format()])?; write!(f, [space()])?; write!(f, [text("as")])?; write!(f, [space()])?; } if let Some(name) = name { write!(f, [dynamic_text(name, TextSize::default())])?; } else { write!(f, [text("_")])?; } } PatternKind::MatchOr { patterns } => { write!(f, [patterns[0].format()])?; for pattern in patterns.iter().skip(1) { write!(f, [space(), text("|"), space(), pattern.format()])?; } } } Ok(()) } }