Fix zulip unstable formatting with end-of-line comments (#6386)

## Bug

Given
```python
x = () - (#
)
```
the comment is a dangling comment of the empty tuple. This is an
end-of-line comment so it may move after the expression. It still
expands the parent, so the operator breaks:
```python
x = (
    ()
    - ()  #
)
```
In the next formatting pass, the comment is not a trailing tuple but a
trailing bin op comment, so the bin op doesn't break anymore. The
comment again expands the parent, so we still add the superfluous
parentheses
```python
x = (
    () - ()  #
)
```

## Fix

The new formatting is to keep the comment on the empty tuple. This is a
log uglier and again has additional outer parentheses, but it's stable:
```python
x = (
    ()
    - (  #
    )
)
```

## Alternatives

Black formats all the examples above as
```python
x = () - ()  #
```
which i find better. 

I would be happy about any suggestions for better solutions than the
current one. I'd mainly need a workaround for expand parent having an
effect on the bin op instead of first moving the comment to the end and
then applying expand parent to the assign statement.
This commit is contained in:
konsti 2023-08-08 11:15:35 +02:00 committed by GitHub
parent 2bd345358f
commit 90ba40c23c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 73 additions and 8 deletions

View file

@ -211,3 +211,14 @@ for user_id in set(target_user_ids) - {u.user_id for u in updates}:
log(self.price / self.strike)
+ (self.risk_free - self.div_cont + 0.5 * (self.sigma**2)) * self.exp_time
) / self.sigmaT
# Stability with end-of-line comments between empty tuples and bin op
x = () - (#
)
x = (
()
- () #
)
x = (
() - () #
)

View file

@ -73,3 +73,7 @@ del (
del ( # dangling end of line comment
)
del ( # dangling end of line comment
# dangling own line comment
) # trailing statement comment

View file

@ -253,6 +253,16 @@ impl<'ast> Format<PyFormatContext<'ast>> for EmptyWithDanglingComments<'_> {
self.opening,
// end-of-line comments
trailing_comments(&self.comments[..end_of_line_split]),
// Avoid unstable formatting with
// ```python
// x = () - (#
// )
// ```
// Without this the comment would go after the empty tuple first, but still expand
// the bin op. In the second formatting pass they are trailing bin op comments
// so the bin op collapse. Suboptimally we keep parentheses around the bin op in
// either case.
(!self.comments[..end_of_line_split].is_empty()).then_some(hard_line_break()),
// own line comments, which need to be indented
soft_block_indent(&dangling_comments(&self.comments[end_of_line_split..])),
self.closing

View file

@ -217,6 +217,17 @@ for user_id in set(target_user_ids) - {u.user_id for u in updates}:
log(self.price / self.strike)
+ (self.risk_free - self.div_cont + 0.5 * (self.sigma**2)) * self.exp_time
) / self.sigmaT
# Stability with end-of-line comments between empty tuples and bin op
x = () - (#
)
x = (
()
- () #
)
x = (
() - () #
)
```
## Output
@ -488,6 +499,19 @@ for user_id in set(target_user_ids) - {u.user_id for u in updates}:
log(self.price / self.strike)
+ (self.risk_free - self.div_cont + 0.5 * (self.sigma**2)) * self.exp_time
) / self.sigmaT
# Stability with end-of-line comments between empty tuples and bin op
x = (
()
- ( #
)
)
x = (
() - () #
)
x = (
() - () #
)
```

View file

@ -213,7 +213,8 @@ f(
a.very_long_function_function_that_is_so_long_that_it_expands_the_parent_but_its_only_a_single_argument()
)
f() # abc
f( # abc
)
f( # abc
# abc

View file

@ -129,7 +129,8 @@ a = {
3: True,
}
x = {} # dangling end of line comment
x = { # dangling end of line comment
}
```

View file

@ -165,7 +165,8 @@ a = (
# Regression test: lambda empty arguments ranges were too long, leading to unstable
# formatting
(
lambda: (), #
lambda: ( #
),
)

View file

@ -62,7 +62,8 @@ c1 = [ # trailing open bracket
```py
# Dangling comment placement in empty lists
# Regression test for https://github.com/python/cpython/blob/03160630319ca26dcbbad65225da4248e54c45ec/Tools/c-analyzer/c_analyzer/datafiles.py#L14-L16
a1 = [] # a
a1 = [ # a
]
a2 = [ # a
# b
]
@ -93,7 +94,8 @@ c1 = [ # trailing open bracket
] # trailing close bracket
[] # end-of-line comment
[ # end-of-line comment
]
[ # end-of-line comment
# own-line comment

View file

@ -79,6 +79,10 @@ del (
del ( # dangling end of line comment
)
del ( # dangling end of line comment
# dangling own line comment
) # trailing statement comment
```
## Output
@ -215,7 +219,12 @@ del (
) # Completed
# Done
del () # dangling end of line comment
del ( # dangling end of line comment
)
del ( # dangling end of line comment
# dangling own line comment
) # trailing statement comment
```

View file

@ -845,7 +845,8 @@ def f( # first
...
def f(): # first # second
def f( # first
): # second
...

View file

@ -192,7 +192,8 @@ raise aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfk < (
) # the other end
# sneaky comment
raise () # another comment
raise ( # another comment
)
raise () # what now