mirror of https://github.com/astral-sh/ruff
Fix leading comment formatting for lambdas with multiple parameters (#21879)
## Summary This is a follow-up to #21868. As soon as I started merging #21868 into #21385, I realized that I had missed a test case with `**kwargs` after the `*args` parameter. Such a case is supposed to be formatted on one line like: ```py # input ( lambda # comment *x, **y: x ) # output ( lambda # comment *x, **y: x ) ``` which you can still see on the [playground](https://play.ruff.rs/bd88d339-1358-40d2-819f-865bfcb23aef?secondary=Format), but on `main` after #21868, this was formatted as: ```py ( lambda # comment *x, **y: x ) ``` because the leading comment on the first parameter caused the whole group around the parameters to break. Instead of making these comments leading comments on the first parameter, this PR makes them leading comments on the parameters list as a whole. ## Test Plan New tests, and I will also try merging this into #21385 _before_ opening it for review this time. <hr> (labeling `internal` since #21868 should not be released before some kind of fix)
This commit is contained in:
parent
a9be810c38
commit
f3714fd3c1
|
|
@ -249,3 +249,25 @@ def a():
|
||||||
x:
|
x:
|
||||||
x
|
x
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
lambda
|
||||||
|
# comment
|
||||||
|
*x,
|
||||||
|
**y: x
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
lambda
|
||||||
|
* # comment 2
|
||||||
|
x,
|
||||||
|
**y:
|
||||||
|
x
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
lambda
|
||||||
|
** # comment 1
|
||||||
|
x:
|
||||||
|
x
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -871,7 +871,20 @@ fn handle_parameter_comment<'a>(
|
||||||
CommentPlacement::Default(comment)
|
CommentPlacement::Default(comment)
|
||||||
}
|
}
|
||||||
} else if comment.start() < parameter.name.start() {
|
} else if comment.start() < parameter.name.start() {
|
||||||
|
// For lambdas, where the parameters cannot be parenthesized and the first parameter thus
|
||||||
|
// starts at the same position as the parent parameters, mark a comment before the first
|
||||||
|
// parameter as leading on the parameters rather than the individual parameter to prevent
|
||||||
|
// the whole parameter list from breaking.
|
||||||
|
//
|
||||||
|
// Note that this check is not needed above because lambda parameters cannot have
|
||||||
|
// annotations.
|
||||||
|
if let Some(AnyNodeRef::Parameters(parameters)) = comment.enclosing_parent()
|
||||||
|
&& parameters.start() == parameter.start()
|
||||||
|
{
|
||||||
|
CommentPlacement::leading(parameters, comment)
|
||||||
|
} else {
|
||||||
CommentPlacement::leading(parameter, comment)
|
CommentPlacement::leading(parameter, comment)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
CommentPlacement::Default(comment)
|
CommentPlacement::Default(comment)
|
||||||
}
|
}
|
||||||
|
|
@ -1835,10 +1848,8 @@ fn handle_lambda_comment<'a>(
|
||||||
// )
|
// )
|
||||||
// ```
|
// ```
|
||||||
if comment.start() < parameters.start() {
|
if comment.start() < parameters.start() {
|
||||||
return if let Some(first) = parameters.iter().next()
|
return if comment.line_position().is_own_line() {
|
||||||
&& comment.line_position().is_own_line()
|
CommentPlacement::leading(parameters, comment)
|
||||||
{
|
|
||||||
CommentPlacement::leading(first.as_parameter(), comment)
|
|
||||||
} else {
|
} else {
|
||||||
CommentPlacement::dangling(comment.enclosing_node(), comment)
|
CommentPlacement::dangling(comment.enclosing_node(), comment)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
|
||||||
.split_at(dangling.partition_point(|comment| comment.end() < parameters.start()));
|
.split_at(dangling.partition_point(|comment| comment.end() < parameters.start()));
|
||||||
|
|
||||||
if dangling_before_parameters.is_empty() {
|
if dangling_before_parameters.is_empty() {
|
||||||
// If the first parameter has a leading comment, insert a hard line break. This
|
// If the parameters have a leading comment, insert a hard line break. This
|
||||||
// comment is associated as a leading comment on the first parameter:
|
// comment is associated as a leading comment on the parameters:
|
||||||
//
|
//
|
||||||
// ```py
|
// ```py
|
||||||
// (
|
// (
|
||||||
|
|
@ -86,11 +86,7 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
|
||||||
// *x: x
|
// *x: x
|
||||||
// )
|
// )
|
||||||
// ```
|
// ```
|
||||||
if parameters
|
if comments.has_leading(&**parameters) {
|
||||||
.iter()
|
|
||||||
.next()
|
|
||||||
.is_some_and(|parameter| comments.has_leading(parameter.as_parameter()))
|
|
||||||
{
|
|
||||||
hard_line_break().fmt(f)?;
|
hard_line_break().fmt(f)?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, [space()])?;
|
write!(f, [space()])?;
|
||||||
|
|
|
||||||
|
|
@ -255,6 +255,28 @@ def a():
|
||||||
x:
|
x:
|
||||||
x
|
x
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
lambda
|
||||||
|
# comment
|
||||||
|
*x,
|
||||||
|
**y: x
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
lambda
|
||||||
|
* # comment 2
|
||||||
|
x,
|
||||||
|
**y:
|
||||||
|
x
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
lambda
|
||||||
|
** # comment 1
|
||||||
|
x:
|
||||||
|
x
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
|
@ -513,4 +535,22 @@ def a():
|
||||||
# comment 2
|
# comment 2
|
||||||
*x: x
|
*x: x
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
lambda
|
||||||
|
# comment
|
||||||
|
*x, **y: x
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
lambda
|
||||||
|
# comment 2
|
||||||
|
*x, **y: x
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
lambda
|
||||||
|
# comment 1
|
||||||
|
**x: x
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue