mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-21 19:05:09 +00:00
Add dangling comment handling for lambda
expressions (#7493)
## Summary This PR adds dangling comment handling for `lambda` expressions. In short, comments around the `lambda` and the `:` are all considered dangling. Comments that come between the `lambda` and the `:` may be moved after the colon for simplicity (this is an odd position for a comment anyway), unless they also precede the lambda parameters, in which case they're formatted before the parameters. Closes https://github.com/astral-sh/ruff/issues/7470. ## Test Plan `cargo test` No change in similarity. Before: | project | similarity index | total files | changed files | |--------------|------------------:|------------------:|------------------:| | cpython | 0.76083 | 1789 | 1632 | | django | 0.99982 | 2760 | 37 | | transformers | 0.99957 | 2587 | 398 | | twine | 1.00000 | 33 | 0 | | typeshed | 0.99983 | 3496 | 18 | | warehouse | 0.99929 | 648 | 16 | | zulip | 0.99962 | 1437 | 22 | After: | project | similarity index | total files | changed files | |--------------|------------------:|------------------:|------------------:| | cpython | 0.76083 | 1789 | 1632 | | django | 0.99982 | 2760 | 37 | | transformers | 0.99957 | 2587 | 398 | | twine | 1.00000 | 33 | 0 | | typeshed | 0.99983 | 3496 | 18 | | warehouse | 0.99929 | 648 | 16 | | zulip | 0.99962 | 1437 | 22 |
This commit is contained in:
parent
e07670ad97
commit
4c4eceee36
5 changed files with 310 additions and 33 deletions
|
@ -229,6 +229,7 @@ fn handle_enclosed_comment<'a>(
|
|||
}
|
||||
AnyNodeRef::ExprUnaryOp(unary_op) => handle_unary_op_comment(comment, unary_op, locator),
|
||||
AnyNodeRef::ExprNamedExpr(_) => handle_named_expr_comment(comment, locator),
|
||||
AnyNodeRef::ExprLambda(lambda) => handle_lambda_comment(comment, lambda, locator),
|
||||
AnyNodeRef::ExprDict(_) => handle_dict_unpacking_comment(comment, locator)
|
||||
.or_else(|comment| handle_bracketed_end_of_line_comment(comment, locator))
|
||||
.or_else(|comment| handle_key_value_comment(comment, locator)),
|
||||
|
@ -1687,6 +1688,119 @@ fn handle_named_expr_comment<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles comments around the `:` token in a lambda expression.
|
||||
///
|
||||
/// For parameterized lambdas, both the comments between the `lambda` and the parameters, and the
|
||||
/// comments between the parameters and the body, are considered dangling, as is the case for all
|
||||
/// of the following:
|
||||
///
|
||||
/// ```python
|
||||
/// (
|
||||
/// lambda # 1
|
||||
/// # 2
|
||||
/// x
|
||||
/// : # 3
|
||||
/// # 4
|
||||
/// y
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// For non-parameterized lambdas, all comments before the body are considered dangling, as is the
|
||||
/// case for all of the following:
|
||||
///
|
||||
/// ```python
|
||||
/// (
|
||||
/// lambda # 1
|
||||
/// # 2
|
||||
/// : # 3
|
||||
/// # 4
|
||||
/// y
|
||||
/// )
|
||||
/// ```
|
||||
fn handle_lambda_comment<'a>(
|
||||
comment: DecoratedComment<'a>,
|
||||
lambda: &'a ast::ExprLambda,
|
||||
locator: &Locator,
|
||||
) -> CommentPlacement<'a> {
|
||||
if let Some(parameters) = lambda.parameters.as_deref() {
|
||||
// Comments between the `lambda` and the parameters are dangling on the lambda:
|
||||
// ```python
|
||||
// (
|
||||
// lambda # comment
|
||||
// x:
|
||||
// y
|
||||
// )
|
||||
// ```
|
||||
if comment.start() < parameters.start() {
|
||||
return CommentPlacement::dangling(comment.enclosing_node(), comment);
|
||||
}
|
||||
|
||||
// Comments between the parameters and the body are dangling on the lambda:
|
||||
// ```python
|
||||
// (
|
||||
// lambda x: # comment
|
||||
// y
|
||||
// )
|
||||
// ```
|
||||
if parameters.end() < comment.start() && comment.start() < lambda.body.start() {
|
||||
// If the value is parenthesized, and the comment is within the parentheses, it should
|
||||
// be a leading comment on the value, not a dangling comment in the lambda, as in:
|
||||
// ```python
|
||||
// (
|
||||
// lambda x: ( # comment
|
||||
// y
|
||||
// )
|
||||
// )
|
||||
// ```
|
||||
let tokenizer = SimpleTokenizer::new(
|
||||
locator.contents(),
|
||||
TextRange::new(parameters.end(), comment.start()),
|
||||
);
|
||||
if tokenizer
|
||||
.skip_trivia()
|
||||
.any(|token| token.kind == SimpleTokenKind::LParen)
|
||||
{
|
||||
return CommentPlacement::Default(comment);
|
||||
}
|
||||
|
||||
return CommentPlacement::dangling(comment.enclosing_node(), comment);
|
||||
}
|
||||
} else {
|
||||
// Comments between the lambda and the body are dangling on the lambda:
|
||||
// ```python
|
||||
// (
|
||||
// lambda: # comment
|
||||
// y
|
||||
// )
|
||||
// ```
|
||||
if comment.start() < lambda.body.start() {
|
||||
// If the value is parenthesized, and the comment is within the parentheses, it should
|
||||
// be a leading comment on the value, not a dangling comment in the lambda, as in:
|
||||
// ```python
|
||||
// (
|
||||
// lambda: ( # comment
|
||||
// y
|
||||
// )
|
||||
// )
|
||||
// ```
|
||||
let tokenizer = SimpleTokenizer::new(
|
||||
locator.contents(),
|
||||
TextRange::new(lambda.start(), comment.start()),
|
||||
);
|
||||
if tokenizer
|
||||
.skip_trivia()
|
||||
.any(|token| token.kind == SimpleTokenKind::LParen)
|
||||
{
|
||||
return CommentPlacement::Default(comment);
|
||||
}
|
||||
|
||||
return CommentPlacement::dangling(comment.enclosing_node(), comment);
|
||||
}
|
||||
}
|
||||
|
||||
CommentPlacement::Default(comment)
|
||||
}
|
||||
|
||||
/// Attach trailing end-of-line comments on the operator as dangling comments on the enclosing
|
||||
/// node.
|
||||
///
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue