Add JoinCommaSeparatedBuilder (#5342)

This commit is contained in:
Micha Reiser 2023-06-23 23:03:05 +02:00 committed by GitHub
parent 6ba9d5d5a4
commit d3d69a031e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 164 additions and 128 deletions

View file

@ -1,14 +1,12 @@
use crate::builders::use_magic_trailing_comma;
use crate::builders::PyFormatterExtensions;
use crate::comments::{dangling_node_comments, Comments};
use crate::context::PyFormatContext;
use crate::expression::parentheses::{
default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
};
use crate::{AsFormat, FormatNodeRule, FormattedIterExt, PyFormatter};
use crate::{AsFormat, FormatNodeRule, PyFormatter};
use ruff_formatter::formatter::Formatter;
use ruff_formatter::prelude::{
block_indent, group, if_group_breaks, soft_block_indent, soft_line_break_or_space, text,
};
use ruff_formatter::prelude::{block_indent, group, if_group_breaks, soft_block_indent, text};
use ruff_formatter::{format_args, write, Buffer, Format, FormatResult, FormatRuleWithOptions};
use ruff_python_ast::prelude::{Expr, Ranged};
use ruff_text_size::TextRange;
@ -61,9 +59,9 @@ impl FormatNodeRule<ExprTuple> for FormatExprTuple {
} = item;
// Handle the edge cases of an empty tuple and a tuple with one element
let last = match &elts[..] {
match elts.as_slice() {
[] => {
return write!(
write!(
f,
[
// An empty tuple always needs parentheses, but does not have a comma
@ -71,10 +69,10 @@ impl FormatNodeRule<ExprTuple> for FormatExprTuple {
block_indent(&dangling_node_comments(item)),
&text(")"),
]
);
)
}
[single] => {
return write!(
write!(
f,
[group(&format_args![
// A single element tuple always needs parentheses and a trailing comma
@ -82,55 +80,38 @@ impl FormatNodeRule<ExprTuple> for FormatExprTuple {
soft_block_indent(&format_args![single.format(), &text(",")]),
&text(")"),
])]
);
)
}
[.., last] => last,
};
let magic_trailing_comma = use_magic_trailing_comma(f, last.range());
if magic_trailing_comma {
// A magic trailing comma forces us to print in expanded mode since we have more than
// one element
write!(
f,
[
// An expanded group always needs parentheses
&text("("),
block_indent(&ExprSequence::new(elts)),
&text(")"),
]
)?;
} else if is_parenthesized(*range, elts, f)
&& self.parentheses != TupleParentheses::StripInsideForLoop
{
// If the tuple has parentheses, we generally want to keep them. The exception are for
// loops, see `TupleParentheses::StripInsideForLoop` doc comment.
//
// Unlike other expression parentheses, tuple parentheses are part of the range of the
// tuple itself.
write!(
f,
[group(&format_args![
// If there were previously parentheses, keep them
&text("("),
soft_block_indent(&ExprSequence::new(elts)),
&text(")"),
])]
)?;
} else {
write!(
f,
[group(&format_args![
// If there were previously no parentheses, add them only if the group breaks
if_group_breaks(&text("(")),
soft_block_indent(&ExprSequence::new(elts)),
if_group_breaks(&text(")")),
])]
)?;
elts if is_parenthesized(*range, elts, f)
&& self.parentheses != TupleParentheses::StripInsideForLoop =>
{
write!(
f,
[group(&format_args![
// If there were previously parentheses, keep them
&text("("),
soft_block_indent(&ExprSequence::new(elts)),
&text(")"),
])]
)
}
elts => {
write!(
f,
[group(&format_args![
// If there were previously no parentheses, add them only if the group breaks
if_group_breaks(&text("(")),
soft_block_indent(&ExprSequence::new(elts)),
if_group_breaks(&text(")")),
])]
)
}
}
Ok(())
}
fn fmt_dangling_comments(&self, _node: &ExprTuple, _f: &mut PyFormatter) -> FormatResult<()> {
@ -152,11 +133,7 @@ impl<'a> ExprSequence<'a> {
impl Format<PyFormatContext<'_>> for ExprSequence<'_> {
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
f.join_with(&format_args!(text(","), soft_line_break_or_space()))
.entries(self.elts.iter().formatted())
.finish()?;
// Black style has a trailing comma on the last entry of an expanded group
write!(f, [if_group_breaks(&text(","))])
f.join_comma_separated().nodes(self.elts.iter()).finish()
}
}