Fix multiline lambda expression statement formating (#8466)

## Summary

This PR fixes a bug in our formatter where a multiline lambda expression
statement was formatted over multiple lines without adding parentheses.

The PR "fixes" the problem by not splitting the lambda parameters if it
is not parenthesized

## Test Plan

Added test
This commit is contained in:
Micha Reiser 2023-11-05 23:35:23 +09:00 committed by GitHub
parent 75c9be099f
commit e57bccd500
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 3 deletions

View file

@ -203,3 +203,28 @@ lambda: ( # comment
y: y:
z z
) )
lambda self, araa, kkkwargs=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(*args, **kwargs), e=1, f=2, g=2: d
# Regression tests for https://github.com/astral-sh/ruff/issues/8179
def a():
return b(
c,
d,
e,
f=lambda self, *args, **kwargs: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(
*args, **kwargs
),
)
def a():
return b(
c,
d,
e,
f=lambda self, araa, kkkwargs,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
args,kwargs,
e=1, f=2, g=2: d,
g = 10
)

View file

@ -102,7 +102,15 @@ impl FormatNodeRule<Parameters> for FormatParameters {
dangling.split_at(parenthesis_comments_end); dangling.split_at(parenthesis_comments_end);
let format_inner = format_with(|f: &mut PyFormatter| { let format_inner = format_with(|f: &mut PyFormatter| {
let separator = format_with(|f| write!(f, [token(","), soft_line_break_or_space()])); let separator = format_with(|f: &mut PyFormatter| {
token(",").fmt(f)?;
if f.context().node_level().is_parenthesized() {
soft_line_break_or_space().fmt(f)
} else {
space().fmt(f)
}
});
let mut joiner = f.join_with(separator); let mut joiner = f.join_with(separator);
let mut last_node: Option<AnyNodeRef> = None; let mut last_node: Option<AnyNodeRef> = None;
@ -232,8 +240,6 @@ impl FormatNodeRule<Parameters> for FormatParameters {
Ok(()) Ok(())
}); });
let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f);
let num_parameters = posonlyargs.len() let num_parameters = posonlyargs.len()
+ args.len() + args.len()
+ usize::from(vararg.is_some()) + usize::from(vararg.is_some())
@ -243,12 +249,14 @@ impl FormatNodeRule<Parameters> for FormatParameters {
if self.parentheses == ParametersParentheses::Never { if self.parentheses == ParametersParentheses::Never {
write!(f, [group(&format_inner), dangling_comments(dangling)]) write!(f, [group(&format_inner), dangling_comments(dangling)])
} else if num_parameters == 0 { } else if num_parameters == 0 {
let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f);
// No parameters, format any dangling comments between `()` // No parameters, format any dangling comments between `()`
write!(f, [empty_parenthesized("(", dangling, ")")]) write!(f, [empty_parenthesized("(", dangling, ")")])
} else { } else {
// Intentionally avoid `parenthesized`, which groups the entire formatted contents. // Intentionally avoid `parenthesized`, which groups the entire formatted contents.
// We want parameters to be grouped alongside return types, one level up, so we // We want parameters to be grouped alongside return types, one level up, so we
// format them "inline" here. // format them "inline" here.
let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f);
write!( write!(
f, f,
[ [

View file

@ -209,6 +209,31 @@ lambda: ( # comment
y: y:
z z
) )
lambda self, araa, kkkwargs=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(*args, **kwargs), e=1, f=2, g=2: d
# Regression tests for https://github.com/astral-sh/ruff/issues/8179
def a():
return b(
c,
d,
e,
f=lambda self, *args, **kwargs: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(
*args, **kwargs
),
)
def a():
return b(
c,
d,
e,
f=lambda self, araa, kkkwargs,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
args,kwargs,
e=1, f=2, g=2: d,
g = 10
)
``` ```
## Output ## Output
@ -413,6 +438,40 @@ lambda: ( # comment
# comment # comment
y: z y: z
) )
lambda self, araa, kkkwargs=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(
*args, **kwargs
), e=1, f=2, g=2: d
# Regression tests for https://github.com/astral-sh/ruff/issues/8179
def a():
return b(
c,
d,
e,
f=lambda self,
*args,
**kwargs: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(*args, **kwargs),
)
def a():
return b(
c,
d,
e,
f=lambda self,
araa,
kkkwargs,
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
args,
kwargs,
e=1,
f=2,
g=2: d,
g=10,
)
``` ```