Extend formatter IR to support Black's expression formatting (#5596)

This commit is contained in:
Micha Reiser 2023-07-11 13:20:04 +02:00 committed by GitHub
parent 212fd86bf0
commit d30e9125eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 576 additions and 56 deletions

View file

@ -1,5 +1,5 @@
use super::tag::Tag;
use crate::format_element::tag::DedentMode;
use crate::format_element::tag::{Condition, DedentMode};
use crate::prelude::tag::GroupMode;
use crate::prelude::*;
use crate::printer::LineEnding;
@ -33,12 +33,17 @@ impl Document {
#[derive(Debug)]
enum Enclosing<'a> {
Group(&'a tag::Group),
ConditionalGroup(&'a tag::ConditionalGroup),
FitsExpanded(&'a tag::FitsExpanded),
BestFitting,
}
fn expand_parent(enclosing: &[Enclosing]) {
if let Some(Enclosing::Group(group)) = enclosing.last() {
group.propagate_expand();
match enclosing.last() {
Some(Enclosing::Group(group)) => group.propagate_expand(),
Some(Enclosing::ConditionalGroup(group)) => group.propagate_expand(),
Some(Enclosing::FitsExpanded(fits_expanded)) => fits_expanded.propagate_expand(),
_ => {}
}
}
@ -58,6 +63,14 @@ impl Document {
Some(Enclosing::Group(group)) => !group.mode().is_flat(),
_ => false,
},
FormatElement::Tag(Tag::StartConditionalGroup(group)) => {
enclosing.push(Enclosing::ConditionalGroup(group));
false
}
FormatElement::Tag(Tag::EndConditionalGroup) => match enclosing.pop() {
Some(Enclosing::ConditionalGroup(group)) => !group.mode().is_flat(),
_ => false,
},
FormatElement::Interned(interned) => match checked_interned.get(interned) {
Some(interned_expands) => *interned_expands,
None => {
@ -79,6 +92,16 @@ impl Document {
enclosing.pop();
continue;
}
FormatElement::Tag(Tag::StartFitsExpanded(fits_expanded)) => {
enclosing.push(Enclosing::FitsExpanded(fits_expanded));
false
}
FormatElement::Tag(Tag::EndFitsExpanded) => {
enclosing.pop();
// Fits expanded acts as a boundary
expands = false;
continue;
}
FormatElement::StaticText { text } => text.contains('\n'),
FormatElement::DynamicText { text, .. } => text.contains('\n'),
FormatElement::SourceCodeSlice {
@ -441,6 +464,29 @@ impl Format<IrFormatContext<'_>> for &[FormatElement] {
}
}
StartConditionalGroup(group) => {
write!(
f,
[
text("conditional_group(condition:"),
space(),
group.condition(),
text(","),
space()
]
)?;
match group.mode() {
GroupMode::Flat => {}
GroupMode::Expand => {
write!(f, [text("expand: true,"), space()])?;
}
GroupMode::Propagated => {
write!(f, [text("expand: propagated,"), space()])?;
}
}
}
StartIndentIfGroupBreaks(id) => {
write!(
f,
@ -491,6 +537,28 @@ impl Format<IrFormatContext<'_>> for &[FormatElement] {
write!(f, [text("fill(")])?;
}
StartFitsExpanded(tag::FitsExpanded {
condition,
propagate_expand,
}) => {
write!(f, [text("fits_expanded(propagate_expand:"), space()])?;
if propagate_expand.get() {
write!(f, [text("true")])?;
} else {
write!(f, [text("false")])?;
}
write!(f, [text(","), space()])?;
if let Some(condition) = condition {
write!(
f,
[text("condition:"), space(), condition, text(","), space()]
)?;
}
}
StartEntry => {
// handled after the match for all start tags
}
@ -503,8 +571,10 @@ impl Format<IrFormatContext<'_>> for &[FormatElement] {
| EndAlign
| EndIndent
| EndGroup
| EndConditionalGroup
| EndLineSuffix
| EndDedent
| EndFitsExpanded
| EndVerbatim => {
write!(f, [ContentArrayEnd, text(")")])?;
}
@ -658,6 +728,31 @@ impl FormatElements for [FormatElement] {
}
}
impl Format<IrFormatContext<'_>> for Condition {
fn fmt(&self, f: &mut Formatter<IrFormatContext>) -> FormatResult<()> {
match (self.mode, self.group_id) {
(PrintMode::Flat, None) => write!(f, [text("if_fits_on_line")]),
(PrintMode::Flat, Some(id)) => write!(
f,
[
text("if_group_fits_on_line("),
dynamic_text(&std::format!("\"{id:?}\""), None),
text(")")
]
),
(PrintMode::Expanded, None) => write!(f, [text("if_breaks")]),
(PrintMode::Expanded, Some(id)) => write!(
f,
[
text("if_group_breaks("),
dynamic_text(&std::format!("\"{id:?}\""), None),
text(")")
]
),
}
}
}
#[cfg(test)]
mod tests {
use crate::prelude::*;