mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-14 06:15:13 +00:00
Add JoinCommaSeparatedBuilder
(#5342)
This commit is contained in:
parent
6ba9d5d5a4
commit
d3d69a031e
4 changed files with 164 additions and 128 deletions
|
@ -1,14 +1,12 @@
|
|||
use crate::builders::use_magic_trailing_comma;
|
||||
use crate::comments::{dangling_node_comments, leading_comments, Comments};
|
||||
use crate::context::PyFormatContext;
|
||||
use crate::expression::parentheses::{
|
||||
default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use crate::{FormatNodeRule, PyFormatter};
|
||||
use ruff_formatter::format_args;
|
||||
use ruff_formatter::{write, Buffer, FormatResult};
|
||||
use crate::FormatNodeRule;
|
||||
use ruff_formatter::{format_args, write};
|
||||
use ruff_python_ast::prelude::Ranged;
|
||||
use ruff_text_size::TextRange;
|
||||
use rustpython_parser::ast::{Expr, ExprDict};
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -19,6 +17,16 @@ struct KeyValuePair<'a> {
|
|||
value: &'a Expr,
|
||||
}
|
||||
|
||||
impl Ranged for KeyValuePair<'_> {
|
||||
fn range(&self) -> TextRange {
|
||||
if let Some(key) = self.key {
|
||||
TextRange::new(key.start(), self.value.end())
|
||||
} else {
|
||||
self.value.range()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Format<PyFormatContext<'_>> for KeyValuePair<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
||||
if let Some(key) = self.key {
|
||||
|
@ -54,57 +62,42 @@ impl FormatNodeRule<ExprDict> for FormatExprDict {
|
|||
values,
|
||||
} = item;
|
||||
|
||||
let last = match &values[..] {
|
||||
[] => {
|
||||
return write!(
|
||||
f,
|
||||
[
|
||||
&text("{"),
|
||||
block_indent(&dangling_node_comments(item)),
|
||||
&text("}"),
|
||||
]
|
||||
);
|
||||
}
|
||||
[.., last] => last,
|
||||
};
|
||||
let magic_trailing_comma = use_magic_trailing_comma(f, last.range());
|
||||
|
||||
debug_assert_eq!(keys.len(), values.len());
|
||||
|
||||
let joined = format_with(|f| {
|
||||
f.join_with(format_args!(text(","), soft_line_break_or_space()))
|
||||
.entries(
|
||||
keys.iter()
|
||||
.zip(values)
|
||||
.map(|(key, value)| KeyValuePair { key, value }),
|
||||
)
|
||||
.finish()
|
||||
});
|
||||
if values.is_empty() {
|
||||
return write!(
|
||||
f,
|
||||
[
|
||||
&text("{"),
|
||||
block_indent(&dangling_node_comments(item)),
|
||||
&text("}"),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
let block = if magic_trailing_comma {
|
||||
block_indent
|
||||
} else {
|
||||
soft_block_indent
|
||||
};
|
||||
let format_pairs = format_with(|f| {
|
||||
let mut joiner = f.join_comma_separated();
|
||||
|
||||
for (key, value) in keys.iter().zip(values) {
|
||||
let key_value_pair = KeyValuePair { key, value };
|
||||
joiner.entry(&key_value_pair, &key_value_pair);
|
||||
}
|
||||
|
||||
joiner.finish()
|
||||
});
|
||||
|
||||
write!(
|
||||
f,
|
||||
[group(&format_args![
|
||||
text("{"),
|
||||
block(&format_args![joined, if_group_breaks(&text(",")),]),
|
||||
soft_block_indent(&format_pairs),
|
||||
text("}")
|
||||
])]
|
||||
)
|
||||
}
|
||||
|
||||
fn fmt_dangling_comments(&self, _node: &ExprDict, _f: &mut PyFormatter) -> FormatResult<()> {
|
||||
// TODO(konstin): Reactivate when string formatting works, currently a source of unstable
|
||||
// formatting, e.g.
|
||||
// ```python
|
||||
// coverage_ignore_c_items = {
|
||||
// # 'cfunction': [...]
|
||||
// }
|
||||
// ```
|
||||
// Handled by `fmt_fields`
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue