Skip to content

Conversation

@ntBre
Copy link
Contributor

@ntBre ntBre commented Dec 9, 2025

Summary

This PR makes two changes to comment placement in lambda parameters. First, we
now insert a line break if the first parameter has a leading comment:

# input
(
    lambda
    * # comment 2
    x:
    x
)

# main
(
    lambda # comment 2
    *x: x
)

# this PR
(
    lambda
	# comment 2
    *x: x
)

Note the missing space in the output from main. This case is currently unstable
on main. Also note that the new formatting is more consistent with our stable
formatting in cases where the lambda has its own dangling comment:

# input
(
    lambda # comment 1
    * # comment 2
    x:
    x
)

# output
(
    lambda  # comment 1
    # comment 2
    *x: x
)

and when a parameter without a comment precedes the split *x:

# input
(
    lambda y,
    * # comment 2
    x:
    x
)

# output
(
    lambda y,
    # comment 2
    *x: x
)

This does change the stable formatting, but I think such cases are rare (expecting zero hits in the ecosystem report), this fixes an existing instability, and it should not change any code we've previously formatted.

Second, this PR modifies the comment placement such that # comment 2 in these
outputs is still a leading comment on the parameter. This is also not the case
on main, where it becomes a dangling lambda comment. This doesn't cause any
instability that I'm aware of on main, but it does cause problems when trying to
adjust the placement of dangling lambda comments in #21385. Changing the
placement in this way should not affect any formatting here.

Test Plan

New lambda tests, plus existing tests covering the cases above with multiple
comments around the parameters (see lambda.py 122-143, and 122-205 or so more
broadly)

I also checked manually that the comments are now leading on the parameter:

❯ cargo run --bin ruff_python_formatter -- --emit stdout --target-version 3.10 --print-comments <<EOF
(
    lambda
        # comment 2
    *x: x
)
EOF
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/ruff_python_formatter --emit stdout --target-version 3.10 --print-comments`
# Comment decoration: Range, Preceding, Following, Enclosing, Comment
21..32, None, Some((Parameters, 37..39)), (ExprLambda, 6..42), "# comment 2"
{
    Node {
        kind: Parameter,
        range: 37..39,
        source: `*x`,
    }: {
        "leading": [
            SourceComment {
                text: "# comment 2",
                position: OwnLine,
                formatted: true,
            },
        ],
        "dangling": [],
        "trailing": [],
    },
}
(
    lambda
    # comment 2
    *x: x
)

But I didn't see a great place to put a test like this. Is there somewhere I can assert this comment placement since it doesn't affect any formatting yet? Or is it okay to wait until we use this in #21385?

ntBre added 6 commits December 9, 2025 12:24
Summary
--

This PR makes two changes to comment placement in lambda paramters. First, we
now insert a line break if the first parameter has a leading comment:

```py
(
    lambda
    * # comment 2
    x:
    x
)

(
    lambda # comment 2
    *x: x
)

(
    lambda
	# comment 2
    *x: x
)
```

Note the missing space in the output from main. This case is currently unstable
on main. Also note that the new formatting is more consistent with our stable
formatting in cases where the lambda has its own dangling comment:

```py
(
    lambda # comment 1
    * # comment 2
    x:
    x
)

(
    lambda  # comment 1
    # comment 2
    *x: x
)
```

and when a parameter without a comment precedes the split `*x`:

```py
(
    lambda y,
    * # comment 2
    x:
    x
)

(
    lambda y,
    # comment 2
    *x: x
)
```

Second, this PR modifies the comment placement such that `# comment 2` in these
outputs is still a leading comment on the parameter. This is also not the case
on main, where it becomes a dangling lambda comment. This doesn't cause any
instability that I'm aware of on main, but it does cause problems when trying to
adjust the placement of dangling lambda comments in #21385. Changing the
placement in this way should not affect the formatting here.

Test Plan
--

New lambda tests, plus existing tests covering the cases above with multiple
comments around the parameters (see lambda.py 122-143, and 122-205 or so more
broadly)
the first of these is unstable because it formats as:

```py
(
    lambda # comment 2
    *x: x
)
```

without the second space before the comment. As a leading comment on the `*x`
parameter, it should instead format like:

```py
(
    lambda
	# comment 2
    *x: x
)
```

which is also consistent with its formatting in the presence of an additional
dangling comment on the lambda itself. this is the second test case added here,
which formats (stably) as:

```py
(
    lambda  # comment 1
    # comment 2
    *x: x
)
```
@ntBre ntBre added formatter Related to the formatter bug Something isn't working labels Dec 9, 2025
@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 9, 2025

ruff-ecosystem results

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

@ntBre ntBre marked this pull request as ready for review December 9, 2025 17:58
@ntBre ntBre requested a review from MichaReiser as a code owner December 9, 2025 17:58
@ntBre ntBre merged commit 0bec5c0 into main Dec 9, 2025
39 checks passed
@ntBre ntBre deleted the brent/lambda-parameter-comments branch December 9, 2025 19:07
ntBre added a commit that referenced this pull request Dec 9, 2025
…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)
dcreager added a commit that referenced this pull request Dec 10, 2025
* origin/main: (33 commits)
  [ty] Simplify union lower bounds and intersection upper bounds in constraint sets (#21871)
  [ty] Collapse `never` paths in constraint set BDDs (#21880)
  Fix leading comment formatting for lambdas with multiple parameters (#21879)
  [ty] Type inference for `@asynccontextmanager` (#21876)
  Fix comment placement in lambda parameters (#21868)
  [`pylint`] Detect subclasses of builtin exceptions (`PLW0133`) (#21382)
  Fix stack overflow with recursive generic protocols (depth limit) (#21858)
  New diagnostics for unused range suppressions (#21783)
  [ty] Use default settings in completion tests
  [ty] Infer type variables within generic unions  (#21862)
  [ty] Fix overload filtering to prefer more "precise" match (#21859)
  [ty] Stabilize auto-import
  [ty] Fix reveal-type E2E test (#21865)
  [ty] Use concise message for LSP clients not supporting related diagnostic information (#21850)
  Include more details in Tokens 'offset is inside token' panic message (#21860)
  apply range suppressions to filter diagnostics (#21623)
  [ty] followup: add-import action for `reveal_type` too (#21668)
  [ty] Enrich function argument auto-complete suggestions with annotated types
  [ty] Add autocomplete suggestions for function arguments
  [`flake8-bugbear`] Accept immutable slice default arguments (`B008`) (#21823)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working formatter Related to the formatter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants