ruff/crates
Dylan 04a3ec3689
Adjust own-line comment placement between branches (#21185)
This PR attempts to improve the placement of own-line comments between
branches in the setting where the comment is more indented than the
preceding node.

There are two main changes.

### First change: Preceding node has leading content

If the preceding node has leading content, we now regard the comment as
automatically _less_ indented than the preceding node, and format
accordingly.

For example, 

```python
if True: preceding_node
# leading on `else`, not trailing on `preceding_node`
else: ...
```

This is more compatible with `black`, although there is a (presumably
very uncommon) edge case:

```python
if True:
    this;that
    # leading on `else`, but trailing in `black`
else: ...
```

I'm sort of okay with this - presumably if one wanted a comment for
those semi-colon separated statements, one should have put it _above_
them, and one wanted a comment only for `that` then it ought to have
been on the same line?

### Second change: searching for last child in body

While searching for the (recursively) last child in the body of the
preceding _branch_, we implicitly assumed that the preceding node had to
have a body to begin the recursion. But actually, in the base case, the
preceding node _is_ the last child in the body of the preceding branch.
So, for example:

```python
if True:
    something
    last_child_but_no_body
    # leading on else for `main` but trailing in this PR
else: ...
```

### More examples

The table below is an attempt to summarize the changes in behavior. The
rows alternate between an example snippet with `while` and the same
example with `if` - in the former case we do _not_ have an `else` node
and in the latter we do.

Notice that:

1. On `main` our handling of `if` vs. `while` is not consistent, whereas
it is consistent in the present PR
2. We disagree with `black` in all cases except that last example on
`main`, but agree in all cases for the present PR (though see above for
a wonky edge case where we disagree).

<table>
<tr>
<th>Original
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>

<th><code>main</code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th>This
PR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>

<th><code>black</code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
</tr>
<tr>
<td>

<pre lang="python">
while True: 
    pass
        # comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
while True:
    pass
else:
    # comment
    pass
</pre>

</td>
<td>

<pre lang="python">
while True:
    pass
    # comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
while True:
    pass
    # comment
else:
    pass
</pre>

</td>
</tr>
<tr>
<td>

<pre lang="python">
if True:
    pass
        # comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
if True:
    pass
# comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
if True:
    pass
    # comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
if True:
    pass
    # comment
else:
    pass
</pre>

</td>
</tr>
<tr>
<td>

<pre lang="python">
while True: pass
# comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
while True:
    pass
    # comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
while True:
    pass
# comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
while True:
    pass
# comment
else:
    pass
</pre>

</td>
</tr>
<tr>
<td>

<pre lang="python">
if True: pass
# comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
if True:
    pass
    # comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
if True:
    pass
# comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
if True:
    pass
# comment
else:
    pass
</pre>

</td>
</tr>
<tr>
<td>

<pre lang="python">
while True: pass
    # comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
while True:
    pass
else:
    # comment
    pass
</pre>

</td>
<td>

<pre lang="python">
while True:
    pass
# comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
while True:
    pass
# comment
else:
    pass
</pre>

</td>
</tr>
<tr>
<td>

<pre lang="python">
if True: pass
    # comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
if True:
    pass
# comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
if True:
    pass
# comment
else:
    pass
</pre>

</td>
<td>

<pre lang="python">
if True:
    pass
# comment
else:
    pass
</pre>

</td>
</tr>
</table>
2025-11-17 07:30:34 -06:00
..
ruff Fix analyze graph tests on windows (#21481) 2025-11-16 18:27:07 +00:00
ruff_annotate_snippets Display diffs for `ruff format --check` and add support for different output formats (#20443) 2025-09-30 12:00:51 -04:00
ruff_benchmark [ty] Faster subscript assignment checks for (unions of) `TypedDict`s (#21378) 2025-11-12 20:16:38 +01:00
ruff_cache Switch to Rust 2024 edition (#18129) 2025-05-16 13:25:28 +02:00
ruff_db [ty] Support for notebooks in VS Code (#21175) 2025-11-13 13:23:19 +01:00
ruff_dev Update Rust toolchain to 1.91 (#21179) 2025-11-01 01:50:58 +00:00
ruff_diagnostics Fix rust feature activation (#20012) 2025-08-21 09:26:06 +02:00
ruff_formatter [ty] Use "cannot" consistently over "can not" (#21255) 2025-11-03 10:38:20 -05:00
ruff_graph `analyze`: Add option to skip over imports in `TYPE_CHECKING` blocks (#21472) 2025-11-16 12:30:24 +00:00
ruff_index Update Rust toolchain to 1.88 and MSRV to 1.86 (#19011) 2025-06-28 20:24:00 +02:00
ruff_linter [`refurb`] Fix `FURB103` autofix (#21454) 2025-11-16 09:32:41 +01:00
ruff_macros Document when a rule was added (#21035) 2025-10-23 14:48:41 -04:00
ruff_memory_usage [ty] Clean up inherited generic contexts (#20647) 2025-10-03 13:55:43 -04:00
ruff_notebook [ty] Respect notebook cell boundaries when adding an auto import (#21322) 2025-11-13 18:58:08 +01:00
ruff_options_metadata Update Rust toolchain to 1.89 (#19807) 2025-08-07 18:21:50 +02:00
ruff_python_ast [`ruff`] Ignore `str()` when not used for simple conversion (`RUF065`) (#21330) 2025-11-10 18:04:41 -05:00
ruff_python_ast_integration_tests Disallow implicit concatenation of t-strings and other string types (#19485) 2025-07-27 12:41:03 +00:00
ruff_python_codegen Configurable "unparse mode" for `ruff_python_codegen::Generator` (#21041) 2025-10-24 15:44:48 +00:00
ruff_python_formatter Adjust own-line comment placement between branches (#21185) 2025-11-17 07:30:34 -06:00
ruff_python_importer [ty] Respect notebook cell boundaries when adding an auto import (#21322) 2025-11-13 18:58:08 +01:00
ruff_python_index Track t-strings and f-strings for token-based rules and suppression comments (#20357) 2025-09-12 13:00:12 -05:00
ruff_python_literal Switch to Rust 2024 edition (#18129) 2025-05-16 13:25:28 +02:00
ruff_python_parser [ty] name is parameter and global is a syntax error (#21312) 2025-11-14 18:15:34 +00:00
ruff_python_semantic [`pyflakes`] Revert to stable behavior if imports for module lie in alternate branches for `F401` (#20878) 2025-10-27 10:23:36 -05:00
ruff_python_stdlib [`ruff`] Extend FA102 with listed PEP 585-compatible APIs (#20659) 2025-10-03 09:45:32 -04:00
ruff_python_trivia Handle t-string prefixes in `SimpleTokenizer` (#20578) 2025-09-25 14:33:37 -05:00
ruff_python_trivia_integration_tests Handle t-string prefixes in `SimpleTokenizer` (#20578) 2025-09-25 14:33:37 -05:00
ruff_server Fix missing diagnostics for notebooks (#21156) 2025-10-31 01:16:43 +00:00
ruff_source_file Move diff rendering to `ruff_db` (#20006) 2025-08-21 09:47:00 -04:00
ruff_text_size [`ruff`] Update schemars to v1 (#20942) 2025-10-20 08:59:52 +02:00
ruff_wasm Bump 0.14.5 (#21435) 2025-11-13 14:37:31 -05:00
ruff_workspace `analyze`: Add option to skip over imports in `TYPE_CHECKING` blocks (#21472) 2025-11-16 12:30:24 +00:00
ty [ty] Improve diagnostic range for `non-subscriptable` diagnostics (#21461) 2025-11-14 21:15:14 +00:00
ty_combine [ty] Disallow std::env and io methods in most ty crates (#20046) 2025-08-22 11:13:47 -07:00
ty_completion_eval [ty] Sync vendored typeshed stubs (#21466) 2025-11-15 17:12:32 +00:00
ty_ide [ty] Inlay hint call argument location (#20349) 2025-11-17 11:33:09 +01:00
ty_project [ty] Fix `--exclude` and `src.exclude` merging (#21341) 2025-11-10 12:52:45 +01:00
ty_python_semantic [ty] Subscript assignment diagnostics follow-up (#21452) 2025-11-17 11:14:58 +00:00
ty_server [ty] Inlay hint call argument location (#20349) 2025-11-17 11:33:09 +01:00
ty_static [ty] improve base conda distinction from child conda (#20675) 2025-10-03 13:56:06 +00:00
ty_test [ty] Provide proper error on dangling revealed (#21416) 2025-11-16 08:34:54 +00:00
ty_vendored [ty] Sync vendored typeshed stubs (#21466) 2025-11-15 17:12:32 +00:00
ty_wasm [ty] Inlay hint call argument location (#20349) 2025-11-17 11:33:09 +01:00