Skip to content

Commit 70968de

Browse files
committed
Indent lambda parameters if parameters wrap
1 parent e7fb0ac commit 70968de

10 files changed

Lines changed: 625 additions & 71 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"preview": "disabled"
4+
},
5+
{
6+
"preview": "enabled"
7+
}
8+
]

crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/lambda.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,71 @@ def f(
204204
z
205205
)
206206

207+
208+
# Leading
209+
lambda x: (
210+
lambda y: lambda z: x
211+
+ y
212+
+ y
213+
+ y
214+
+ y
215+
+ y
216+
+ y
217+
+ y
218+
+ y
219+
+ y
220+
+ y
221+
+ y
222+
+ y
223+
+ y
224+
+ y
225+
+ y
226+
+ y
227+
+ y
228+
+ y
229+
+ y
230+
+ y
231+
+ y
232+
+ z # Trailing
233+
) # Trailing
234+
235+
236+
# Leading
237+
lambda x: lambda y: lambda z: [
238+
x,
239+
y,
240+
y,
241+
y,
242+
y,
243+
y,
244+
y,
245+
y,
246+
y,
247+
y,
248+
y,
249+
y,
250+
y,
251+
y,
252+
y,
253+
y,
254+
y,
255+
y,
256+
y,
257+
y,
258+
y,
259+
y,
260+
y,
261+
y,
262+
y,
263+
y,
264+
y,
265+
y,
266+
y,
267+
y,
268+
z
269+
] # Trailing
270+
# Trailing
271+
207272
lambda self, araa, kkkwargs=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(*args, **kwargs), e=1, f=2, g=2: d
208273

209274
# Regression tests for https://github.com/astral-sh/ruff/issues/8179

crates/ruff_python_formatter/src/comments/placement.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,18 +1805,6 @@ fn handle_lambda_comment<'a>(
18051805
locator: &Locator,
18061806
) -> CommentPlacement<'a> {
18071807
if let Some(parameters) = lambda.parameters.as_deref() {
1808-
// Comments between the `lambda` and the parameters are dangling on the lambda:
1809-
// ```python
1810-
// (
1811-
// lambda # comment
1812-
// x:
1813-
// y
1814-
// )
1815-
// ```
1816-
if comment.start() < parameters.start() {
1817-
return CommentPlacement::dangling(comment.enclosing_node(), comment);
1818-
}
1819-
18201808
// Comments between the parameters and the body are dangling on the lambda:
18211809
// ```python
18221810
// (

crates/ruff_python_formatter/src/context.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ impl<'a> PyFormatContext<'a> {
4343
pub(crate) fn comments(&self) -> &Comments<'a> {
4444
&self.comments
4545
}
46+
47+
pub(crate) const fn is_preview(&self) -> bool {
48+
self.options.preview().is_enabled()
49+
}
50+
51+
pub(crate) const fn is_stable(&self) -> bool {
52+
!self.is_preview()
53+
}
4654
}
4755

4856
impl FormatContext for PyFormatContext<'_> {

crates/ruff_python_formatter/src/expression/expr_lambda.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use ruff_python_ast::ExprLambda;
44
use ruff_text_size::Ranged;
55

66
use crate::comments::{dangling_comments, SourceComment};
7-
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
7+
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses, Parenthesize};
8+
use crate::expression::{has_own_parentheses, maybe_parenthesize_expression};
89
use crate::other::parameters::ParametersParentheses;
910
use crate::prelude::*;
1011

@@ -25,7 +26,7 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
2526
write!(f, [token("lambda")])?;
2627

2728
if let Some(parameters) = parameters {
28-
// In this context, a dangling comment can either be a comment between the `lambda` the
29+
// In this context, a dangling comment can either be a comment between the `lambda` and the
2930
// parameters, or a comment between the parameters and the body.
3031
let (dangling_before_parameters, dangling_after_parameters) = dangling
3132
.split_at(dangling.partition_point(|comment| comment.end() < parameters.start()));
@@ -36,20 +37,30 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
3637
write!(f, [dangling_comments(dangling_before_parameters)])?;
3738
}
3839

39-
write!(
40-
f,
41-
[parameters
42-
.format()
43-
.with_options(ParametersParentheses::Never)]
44-
)?;
40+
group(&format_with(|f: &mut PyFormatter| {
41+
if f.context().node_level().is_parenthesized() {
42+
soft_block_indent(
43+
&parameters
44+
.format()
45+
.with_options(ParametersParentheses::Never),
46+
)
47+
.fmt(f)
48+
} else {
49+
parameters
50+
.format()
51+
.with_options(ParametersParentheses::Never)
52+
.fmt(f)
53+
}?;
4554

46-
write!(f, [token(":")])?;
55+
token(":").fmt(f)?;
4756

48-
if dangling_after_parameters.is_empty() {
49-
write!(f, [space()])?;
50-
} else {
51-
write!(f, [dangling_comments(dangling_after_parameters)])?;
52-
}
57+
if dangling_after_parameters.is_empty() {
58+
space().fmt(f)
59+
} else {
60+
dangling_comments(dangling_after_parameters).fmt(f)
61+
}
62+
}))
63+
.fmt(f)?;
5364
} else {
5465
write!(f, [token(":")])?;
5566

@@ -61,7 +72,12 @@ impl FormatNodeRule<ExprLambda> for FormatExprLambda {
6172
}
6273
}
6374

64-
write!(f, [body.format()])
75+
// Avoid parenthesizing lists, dictionaries, etc.
76+
if f.context().is_stable() || has_own_parentheses(body, f.context()).is_some() {
77+
body.format().fmt(f)
78+
} else {
79+
maybe_parenthesize_expression(body, item, Parenthesize::IfBreaksOrIfRequired).fmt(f)
80+
}
6581
}
6682

6783
fn fmt_dangling_comments(

crates/ruff_python_formatter/src/expression/expr_named_expr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ impl NeedsParentheses for ExprNamedExpr {
6969
|| parent.is_stmt_delete()
7070
|| parent.is_stmt_for()
7171
|| parent.is_stmt_function_def()
72+
|| parent.is_expr_lambda()
7273
{
7374
OptionalParentheses::Always
7475
} else {

crates/ruff_python_formatter/src/lib.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,7 @@ if True:
206206
#[test]
207207
fn quick_test() {
208208
let source = r#"
209-
def main() -> None:
210-
if True:
211-
some_very_long_variable_name_abcdefghijk = Foo()
212-
some_very_long_variable_name_abcdefghijk = some_very_long_variable_name_abcdefghijk[
213-
some_very_long_variable_name_abcdefghijk.some_very_long_attribute_name
214-
== "This is a very long string abcdefghijk"
215-
]
216-
209+
lambda self, araa, kkkwargs=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(*args, **kwargs), e=1, f=2, g=2: d
217210
"#;
218211
let source_type = PySourceType::Python;
219212
let (tokens, comment_ranges) = tokens_and_ranges(source, source_type).unwrap();

crates/ruff_python_formatter/src/options.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl PyFormatOptions {
108108
self.line_ending
109109
}
110110

111-
pub fn preview(&self) -> PreviewMode {
111+
pub const fn preview(&self) -> PreviewMode {
112112
self.preview
113113
}
114114

crates/ruff_python_formatter/src/other/parameters.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ impl FormatNodeRule<Parameters> for FormatParameters {
247247
+ usize::from(kwarg.is_some());
248248

249249
if self.parentheses == ParametersParentheses::Never {
250-
write!(f, [group(&format_inner), dangling_comments(dangling)])
250+
write!(f, [format_inner, dangling_comments(dangling)])
251251
} else if num_parameters == 0 {
252252
let mut f = WithNodeLevel::new(NodeLevel::ParenthesizedExpression, f);
253253
// No parameters, format any dangling comments between `()`

0 commit comments

Comments
 (0)