Formatter: Add EmptyWithDanglingComments helper (#5951)

**Summary** Add a `EmptyWithDanglingComments` format helper that formats
comments inside empty parentheses, brackets or curly braces. Previously,
this was implemented separately, and partially incorrectly, for each use
case.

Empty `()`, `[]` and `{}` are special because there can be dangling
comments, and they can be in
two positions:
```python
x = [  # end-of-line
    # own line
]
```
These comments are dangling because they can't be assigned to any
element inside as they would
in all other cases.

**Test Plan** Added a regression test.

145 (from previously 149) instances of unstable formatting remaining.

```
$ cargo run --bin ruff_dev --release -- format-dev --stability-check --error-file formatter-ecosystem-errors.txt --multi-project target/checkouts > formatter-ecosystem-progress.txt
$ rg "Unstable formatting" target/formatter-ecosystem-errors.txt | wc -l
145
```
This commit is contained in:
konsti 2023-07-23 14:32:16 +02:00 committed by GitHub
parent f886b58c92
commit 46f8961292
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 94 additions and 56 deletions

View file

@ -5,8 +5,7 @@ use rustpython_parser::ast::{Expr, Ranged};
use ruff_formatter::{format_args, write, FormatRuleWithOptions};
use ruff_python_ast::node::AnyNodeRef;
use crate::builders::parenthesize_if_expands;
use crate::comments::{dangling_comments, CommentLinePosition};
use crate::builders::{empty_parenthesized_with_dangling_comments, parenthesize_if_expands};
use crate::expression::parentheses::{
parenthesized, NeedsParentheses, OptionalParentheses, Parentheses,
};
@ -79,22 +78,12 @@ impl FormatNodeRule<ExprTuple> for FormatExprTuple {
match elts.as_slice() {
[] => {
let comments = f.context().comments().clone();
let dangling = comments.dangling_comments(item);
let end_of_line_split = dangling.partition_point(|comment| {
comment.line_position() == CommentLinePosition::EndOfLine
});
debug_assert!(dangling[end_of_line_split..]
.iter()
.all(|comment| comment.line_position() == CommentLinePosition::OwnLine));
write!(
f,
[group(&format_args![
text("("),
dangling_comments(&dangling[..end_of_line_split]),
soft_block_indent(&dangling_comments(&dangling[end_of_line_split..])),
text(")")
])]
return empty_parenthesized_with_dangling_comments(
text("("),
comments.dangling_comments(item),
text(")"),
)
.fmt(f);
}
[single] => match self.parentheses {
TupleParentheses::Subscript