ruff/crates/ruff_python_formatter/src/expression
Charlie Marsh a3d4f08f29
Add general support for parenthesized comments on expressions (#6485)
## Summary

This PR adds support for parenthesized comments. A parenthesized comment
is a comment that appears within a parenthesis, but not within the range
of the expression enclosed by the parenthesis. For example, the comment
here is a parenthesized comment:

```python
if (
    # comment
    True
):
    ...
```

The parentheses enclose the `True`, but the range of `True` doesn’t
include the `# comment`.

There are at least two problems associated with parenthesized comments:
(1) associating the comment with the correct (i.e., enclosed) node; and
(2) formatting the comment correctly, once it has been associated with
the enclosed node.

The solution proposed here for (1) is to search for parentheses between
preceding and following node, and use open and close parentheses to
break ties, rather than always assigning to the preceding node.

For (2), we handle these special parenthesized comments in `FormatExpr`.
The biggest risk with this approach is that we forget some codepath that
force-disables parenthesization (by passing in `Parentheses::Never`).
I've audited all usages of that enum and added additional handling +
test coverage for such cases.

Closes https://github.com/astral-sh/ruff/issues/6390.

## Test Plan

`cargo test` with new cases.

Before:

| project      | similarity index |
|--------------|------------------|
| build        | 0.75623          |
| cpython      | 0.75472          |
| django       | 0.99804          |
| transformers | 0.99618          |
| typeshed     | 0.74233          |
| warehouse    | 0.99601          |
| zulip        | 0.99727          |

After:

| project      | similarity index |
|--------------|------------------|
| build        | 0.75623          |
| cpython      | 0.75472          |
| django       | 0.99804          |
| transformers | 0.99618          |
| typeshed     | 0.74237          |
| warehouse    | 0.99601          |
| zulip        | 0.99727          |
2023-08-15 18:59:18 +00:00
..
expr_attribute.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_await.rs Pull in RustPython parser (#6099) 2023-07-27 09:29:11 +00:00
expr_bin_op.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_bool_op.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_call.rs Call chain formatting in fluent style (#6151) 2023-08-04 13:58:01 +00:00
expr_compare.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_constant.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_dict.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_dict_comp.rs Add a with_dangling_comments to the parenthesized formatter (#6402) 2023-08-07 19:12:12 +00:00
expr_f_string.rs Rename JoinedStr to FString in the AST (#6379) 2023-08-07 17:33:17 +00:00
expr_formatted_value.rs Track formatting all comments 2023-08-10 09:19:27 +02:00
expr_generator_exp.rs Add general support for parenthesized comments on expressions (#6485) 2023-08-15 18:59:18 +00:00
expr_if_exp.rs Pull in RustPython parser (#6099) 2023-07-27 09:29:11 +00:00
expr_ipy_escape_command.rs fmt: off..on suppression comments (#6477) 2023-08-14 15:57:36 +00:00
expr_lambda.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_list.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_list_comp.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_name.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_named_expr.rs Add test case for walrus operators in return types (#6438) 2023-08-11 18:28:48 +00:00
expr_set.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_set_comp.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_slice.rs Pull in RustPython parser (#6099) 2023-07-27 09:29:11 +00:00
expr_starred.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_subscript.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_tuple.rs Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
expr_unary_op.rs Pull in RustPython parser (#6099) 2023-07-27 09:29:11 +00:00
expr_yield.rs Replace Formatter<PyFormatContext<'_>> with PyFormatter (#6330) 2023-08-04 10:48:58 +02:00
expr_yield_from.rs Add AnyExpressionYield to consolidate ExprYield and ExprYieldFrom (#6127) 2023-07-27 16:01:16 +00:00
mod.rs Add general support for parenthesized comments on expressions (#6485) 2023-08-15 18:59:18 +00:00
number.rs Replace Formatter<PyFormatContext<'_>> with PyFormatter (#6330) 2023-08-04 10:48:58 +02:00
parentheses.rs Allow return type annotations to use their own parentheses (#6436) 2023-08-11 18:19:21 +00:00
string.rs Replace dynamic implicit concatenation detection with parser flag (#6513) 2023-08-14 10:27:17 -04:00