mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-19 10:01:15 +00:00
Parenthesize with statements (#5758)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary This PR improves the parentheses handling for with items to get closer to black's formatting. ### Case 1: ```python # Black / Input with ( [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbb", "cccccccccccccccccccccccccccccccccccccccccc", dddddddddddddddddddddddddddddddd, ] as example1, aaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccccccccccccccc + ddddddddddddddddd as example2, CtxManager2() as example2, CtxManager2() as example2, CtxManager2() as example2, ): ... # Before with ( [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbb", "cccccccccccccccccccccccccccccccccccccccccc", dddddddddddddddddddddddddddddddd, ] as example1, ( aaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccccccccccccccc + ddddddddddddddddd ) as example2, CtxManager2() as example2, CtxManager2() as example2, CtxManager2() as example2, ): ... ``` Notice how Ruff wraps the binary expression in an extra set of parentheses ### Case 2: Black does not expand the with-items if the with has no parentheses: ```python # Black / Input with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as c: ... # Before with ( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as c ): ... ``` Or ```python # Black / Input with [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbb", "cccccccccccccccccccccccccccccccccccccccccc", dddddddddddddddddddddddddddddddd, ] as example1, aaaaaaaaaaaaaaaaaaaaaaaaaa * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccc + ddddddddddddddddd as example2, CtxManager222222222222222() as example2: ... # Before (Same as Case 1) with ( [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbb", "cccccccccccccccccccccccccccccccccccccccccc", dddddddddddddddddddddddddddddddd, ] as example1, ( aaaaaaaaaaaaaaaaaaaaaaaaaa * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccc + ddddddddddddddddd ) as example2, CtxManager222222222222222() as example2, ): ... ``` ## Test Plan I added new snapshot tests Improves the django similarity index from 0.973 to 0.977
This commit is contained in:
parent
e1c119fde3
commit
3cda89ecaf
13 changed files with 443 additions and 141 deletions
|
@ -40,6 +40,7 @@ pub(super) fn place_comment<'a>(
|
|||
handle_expr_if_comment,
|
||||
handle_comprehension_comment,
|
||||
handle_trailing_expression_starred_star_end_of_line_comment,
|
||||
handle_with_item_comment,
|
||||
];
|
||||
for handler in HANDLERS {
|
||||
comment = match handler(comment, locator) {
|
||||
|
@ -1232,6 +1233,50 @@ fn handle_trailing_expression_starred_star_end_of_line_comment<'a>(
|
|||
CommentPlacement::leading(starred.as_any_node_ref(), comment)
|
||||
}
|
||||
|
||||
/// Handles trailing own line comments before the `as` keyword of a with item and
|
||||
/// end of line comments that are on the same line as the `as` keyword:
|
||||
///
|
||||
/// ```python
|
||||
/// with (
|
||||
/// a
|
||||
/// # trailing a own line comment
|
||||
/// as # trailing as same line comment
|
||||
/// b
|
||||
// ): ...
|
||||
/// ```
|
||||
fn handle_with_item_comment<'a>(
|
||||
comment: DecoratedComment<'a>,
|
||||
locator: &Locator,
|
||||
) -> CommentPlacement<'a> {
|
||||
if !comment.enclosing_node().is_with_item() {
|
||||
return CommentPlacement::Default(comment);
|
||||
}
|
||||
|
||||
// Needs to be a with item with an `as` expression.
|
||||
let (Some(context_expr), Some(optional_vars)) =
|
||||
(comment.preceding_node(), comment.following_node())
|
||||
else {
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
|
||||
let as_token = find_only_token_in_range(
|
||||
TextRange::new(context_expr.end(), optional_vars.start()),
|
||||
locator,
|
||||
TokenKind::As,
|
||||
);
|
||||
|
||||
// If before the `as` keyword, then it must be a trailing comment of the context expression.
|
||||
if comment.end() < as_token.start() {
|
||||
CommentPlacement::trailing(context_expr, comment)
|
||||
}
|
||||
// Trailing end of line comment coming after the `as` keyword`.
|
||||
else if comment.line_position().is_end_of_line() {
|
||||
CommentPlacement::dangling(comment.enclosing_node(), comment)
|
||||
} else {
|
||||
CommentPlacement::Default(comment)
|
||||
}
|
||||
}
|
||||
|
||||
/// Looks for a token in the range that contains no other tokens except for parentheses outside
|
||||
/// the expression ranges
|
||||
fn find_only_token_in_range(range: TextRange, locator: &Locator, token_kind: TokenKind) -> Token {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue