From e57bccd500d1a816ed929c5449b73bc763675681 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Sun, 5 Nov 2023 23:35:23 +0900 Subject: [PATCH] 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 --- .../test/fixtures/ruff/expression/lambda.py | 25 ++++++++ .../src/other/parameters.rs | 14 ++++- .../format@expression__lambda.py.snap | 59 +++++++++++++++++++ 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/lambda.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/lambda.py index 3677fedb70..4a7090ff13 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/lambda.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/lambda.py @@ -203,3 +203,28 @@ lambda: ( # comment 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 + ) + diff --git a/crates/ruff_python_formatter/src/other/parameters.rs b/crates/ruff_python_formatter/src/other/parameters.rs index 5e67e579de..86cad5869b 100644 --- a/crates/ruff_python_formatter/src/other/parameters.rs +++ b/crates/ruff_python_formatter/src/other/parameters.rs @@ -102,7 +102,15 @@ impl FormatNodeRule for FormatParameters { dangling.split_at(parenthesis_comments_end); 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 last_node: Option = None; @@ -232,8 +240,6 @@ impl FormatNodeRule for FormatParameters { Ok(()) }); - let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f); - let num_parameters = posonlyargs.len() + args.len() + usize::from(vararg.is_some()) @@ -243,12 +249,14 @@ impl FormatNodeRule for FormatParameters { if self.parentheses == ParametersParentheses::Never { write!(f, [group(&format_inner), dangling_comments(dangling)]) } else if num_parameters == 0 { + let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f); // No parameters, format any dangling comments between `()` write!(f, [empty_parenthesized("(", dangling, ")")]) } else { // Intentionally avoid `parenthesized`, which groups the entire formatted contents. // We want parameters to be grouped alongside return types, one level up, so we // format them "inline" here. + let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f); write!( f, [ diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__lambda.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__lambda.py.snap index 8f615a6511..241f61a481 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__lambda.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__lambda.py.snap @@ -209,6 +209,31 @@ lambda: ( # comment 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 + ) + ``` ## Output @@ -413,6 +438,40 @@ lambda: ( # comment # comment 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, + ) ```