Handle comments on open parentheses in with statements (#6515)

## Summary

This PR adds handling for comments on open parentheses in parenthesized
context managers. For example, given:

```python
with (  # comment
    CtxManager1() as example1,
    CtxManager2() as example2,
    CtxManager3() as example3,
):
    ...
```

We want to preserve that formatting. (Black does the same.) On `main`,
we format as:

```python
with (
    # comment
    CtxManager1() as example1,
    CtxManager2() as example2,
    CtxManager3() as example3,
):
    ...
```

It's very similar to how `StmtImportFrom` is handled.

Note that this case _isn't_ covered by the "parenthesized comment"
proposal, since this is a common on the statement that would typically
be attached to the first `WithItem`, and the `WithItem` _itself_ can
have parenthesized comments, like:

```python
with (  # comment
    (
        CtxManager1()  # comment
    ) as example1,
    CtxManager2() as example2,
    CtxManager3() as example3,
):
    ...
```

## Test Plan

`cargo test`

Confirmed no change in similarity score.
This commit is contained in:
Charlie Marsh 2023-08-14 11:11:03 -04:00 committed by GitHub
parent 3711f8ad59
commit c3a9151eb5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 148 additions and 19 deletions

View file

@ -73,6 +73,7 @@ pub(super) fn place_comment<'a>(
handle_leading_class_with_decorators_comment(comment, class_def)
}
AnyNodeRef::StmtImportFrom(import_from) => handle_import_from_comment(comment, import_from),
AnyNodeRef::StmtWith(with_) => handle_with_comment(comment, with_),
AnyNodeRef::ExprConstant(_) => {
if let Some(AnyNodeRef::ExprFString(fstring)) = comment.enclosing_parent() {
CommentPlacement::dangling(fstring, comment)
@ -1172,7 +1173,7 @@ fn handle_bracketed_end_of_line_comment<'a>(
CommentPlacement::Default(comment)
}
/// Attach an enclosed end-of-line comment to a [`StmtImportFrom`].
/// Attach an enclosed end-of-line comment to a [`ast::StmtImportFrom`].
///
/// For example, given:
/// ```python
@ -1181,8 +1182,8 @@ fn handle_bracketed_end_of_line_comment<'a>(
/// )
/// ```
///
/// The comment will be attached to the `StmtImportFrom` node as a dangling comment, to ensure
/// that it remains on the same line as the `StmtImportFrom` itself.
/// The comment will be attached to the [`ast::StmtImportFrom`] node as a dangling comment, to
/// ensure that it remains on the same line as the [`ast::StmtImportFrom`] itself.
fn handle_import_from_comment<'a>(
comment: DecoratedComment<'a>,
import_from: &'a ast::StmtImportFrom,
@ -1217,6 +1218,35 @@ fn handle_import_from_comment<'a>(
}
}
/// Attach an enclosed end-of-line comment to a [`ast::StmtWith`].
///
/// For example, given:
/// ```python
/// with ( # foo
/// CtxManager1() as example1,
/// CtxManager2() as example2,
/// CtxManager3() as example3,
/// ):
/// ...
/// ```
///
/// The comment will be attached to the [`ast::StmtWith`] node as a dangling comment, to ensure
/// that it remains on the same line as the [`ast::StmtWith`] itself.
fn handle_with_comment<'a>(
comment: DecoratedComment<'a>,
with_statement: &'a ast::StmtWith,
) -> CommentPlacement<'a> {
if comment.line_position().is_end_of_line()
&& with_statement.items.first().is_some_and(|with_item| {
with_statement.start() < comment.start() && comment.start() < with_item.start()
})
{
CommentPlacement::dangling(comment.enclosing_node(), comment)
} else {
CommentPlacement::Default(comment)
}
}
// Handle comments inside comprehensions, e.g.
//
// ```python