ruff/crates/ruff_python_formatter/tests/snapshots
Charlie Marsh 376d3caf47
Treat empty-line separated comments as trailing statement comments (#6999)
## Summary

This PR modifies our between-statement comment handling such that
comments that are not separated by a statement by any newlines continue
to be treated as leading comments on the statement, but comments that
_are_ separated are instead formatted as trailing comments on the
preceding statement.

See, e.g., the originating snippet:

```python
DEFAULT_TEMPLATE = "flatpages/default.html"

# This view is called from FlatpageFallbackMiddleware.process_response
# when a 404 is raised, which often means CsrfViewMiddleware.process_view
# has not been called even if CsrfViewMiddleware is installed. So we need
# to use @csrf_protect, in case the template needs {% csrf_token %}.
# However, we can't just wrap this view; if no matching flatpage exists,
# or a redirect is required for authentication, the 404 needs to be returned
# without any CSRF checks. Therefore, we only
# CSRF protect the internal implementation.


def flatpage(request, url):
    pass
```

Here, we need to ensure that the `def flatpage` is precede by two empty
lines. However, we want those two empty lines to be enforced from the
_end_ of the comment block, _unless_ the comments are directly atop the
`def flatpage`.

I played with this a bit, and I think the simplest conceptual model and
implementation is to instead treat those as trailing comments on the
preceding node. The main difficulty with this approach is that, in order
to be fully compatible with Black, we'd sometimes need to insert
newlines _between_ the preceding node and its trailing comments. See,
e.g.:

```python
def func():
    ...
# comment

x = 1
```

In this case, we'd need to insert two blank lines between `def func():
...` and `# comment`, but `# comment` is trailing comment on `def
func(): ...`. So, we'd need to take this case into account in the
various nodes that _require_ newlines after them: functions, classes,
and imports. After some discussion, we've opted _not_ to support this,
and just treat these as trailing comments -- so we won't insert newlines
there. This means our handling is still identical to Black's on
Black-formatted code, but avoids moving such trailing comments on
unformatted code.

I dislike that the empty handling is so complex, and that it's split
between so many different nodes, but this is really tricky. Continuing
to treat these as leading comments is very difficult too, since we'd
need to do similar tricks for the leading comment handling in those
nodes, and influencing leading comments is even harder, since they're
all formatted _before_ the node itself.

Closes https://github.com/astral-sh/ruff/issues/6761.

## Test Plan

`cargo test`

Surprisingly, it doesn't change the similarity at all (apart from a
0.00001 change in CPython), but I manually confirmed that it did fix the
originating issue in Django.

Before:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.76082          |
| django       | 0.99921          |
| transformers | 0.99854          |
| twine        | 0.99982          |
| typeshed     | 0.99953          |
| warehouse    | 0.99648          |
| zulip        | 0.99928          |


After:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.76081          |
| django       | 0.99921          |
| transformers | 0.99854          |
| twine        | 0.99982          |
| typeshed     | 0.99953          |
| warehouse    | 0.99648          |
| zulip        | 0.99928          |
2023-08-31 20:55:05 +00:00
..
black_compatibility@conditional_expression.py.snap Don't "flatten" nested if expressions when formatting (#6996) 2023-08-30 04:11:58 +00:00
black_compatibility@miscellaneous__blackd_diff.py.snap Update Black tests (#5438) 2023-06-30 06:32:50 +00:00
black_compatibility@miscellaneous__debug_visitor.py.snap format ExprJoinedStr (#5932) 2023-08-01 08:26:30 +02:00
black_compatibility@miscellaneous__decorators.py.snap Treat empty-line separated comments as trailing statement comments (#6999) 2023-08-31 20:55:05 +00:00
black_compatibility@miscellaneous__docstring_no_string_normalization.py.snap Format docstrings (#6452) 2023-08-14 12:28:58 +00:00
black_compatibility@miscellaneous__docstring_preview_no_string_normalization.py.snap format ExprJoinedStr (#5932) 2023-08-01 08:26:30 +02:00
black_compatibility@miscellaneous__force_pyi.py.snap Format target: annotation = value? expressions (#5661) 2023-07-11 16:40:28 +02:00
black_compatibility@miscellaneous__long_strings_flag_disabled.py.snap Maybe parenthesize long constants and names (#6816) 2023-08-24 09:47:57 +00:00
black_compatibility@miscellaneous__power_op_newline.py.snap Update Black tests (#5438) 2023-06-30 06:32:50 +00:00
black_compatibility@miscellaneous__string_quotes.py.snap format ExprJoinedStr (#5932) 2023-08-01 08:26:30 +02:00
black_compatibility@py_38__pep_572_remove_parens.py.snap Update Black tests (#6618) 2023-08-16 15:05:51 +00:00
black_compatibility@py_39__python39.py.snap Remove parentheses around some walrus operators (#6173) 2023-07-29 10:06:26 -04:00
black_compatibility@py_310__pattern_matching_extras.py.snap Format PatternMatchOr (#6905) 2023-08-28 08:09:17 +00:00
black_compatibility@py_310__pattern_matching_style.py.snap Introduce AST nodes for PatternMatchClass arguments (#6881) 2023-08-26 14:45:44 +00:00
black_compatibility@py_310__pep_572_py310.py.snap Format expr generator exp (#5804) 2023-07-19 13:01:58 +02:00
black_compatibility@simple_cases__attribute_access_on_number_literals.py.snap Format numeric constants (#5972) 2023-07-24 07:04:40 +00:00
black_compatibility@simple_cases__comment_after_escaped_newline.py.snap Update Black tests (#5438) 2023-06-30 06:32:50 +00:00
black_compatibility@simple_cases__comments2.py.snap Add trailing comma for single-element import-from groups (#6583) 2023-08-15 07:15:33 -04:00
black_compatibility@simple_cases__comments6.py.snap Use reserved width to include line suffix measurement (#6901) 2023-08-30 08:07:11 +00:00
black_compatibility@simple_cases__comments9.py.snap Remove newline-insertion logic from JoinNodesBuilder (#6205) 2023-07-31 16:58:15 -04:00
black_compatibility@simple_cases__composition.py.snap Avoid parenthesizing multiline strings in binary expressions (#6973) 2023-08-30 16:03:17 +02:00
black_compatibility@simple_cases__composition_no_trailing_comma.py.snap Avoid parenthesizing multiline strings in binary expressions (#6973) 2023-08-30 16:03:17 +02:00
black_compatibility@simple_cases__docstring_preview.py.snap Format docstrings (#6452) 2023-08-14 12:28:58 +00:00
black_compatibility@simple_cases__expression.py.snap Group binary operators with same precedence only (#7010) 2023-08-31 09:19:45 +02:00
black_compatibility@simple_cases__fmtonoff.py.snap Treat empty-line separated comments as trailing statement comments (#6999) 2023-08-31 20:55:05 +00:00
black_compatibility@simple_cases__fmtonoff4.py.snap fmt: off..on suppression comments (#6477) 2023-08-14 15:57:36 +00:00
black_compatibility@simple_cases__fmtonoff5.py.snap Treat empty-line separated comments as trailing statement comments (#6999) 2023-08-31 20:55:05 +00:00
black_compatibility@simple_cases__fmtpass_imports.py.snap Treat empty-line separated comments as trailing statement comments (#6999) 2023-08-31 20:55:05 +00:00
black_compatibility@simple_cases__fmtskip5.py.snap Improve comprehension line break beheavior 2023-07-11 16:51:24 +02:00
black_compatibility@simple_cases__function.py.snap Call chain formatting in fluent style (#6151) 2023-08-04 13:58:01 +00:00
black_compatibility@simple_cases__function2.py.snap Add empty lines before nested functions and classes (#6206) 2023-08-01 15:30:59 +00:00
black_compatibility@simple_cases__ignore_pyi.py.snap Rewrite placement logic (#6040) 2023-07-26 16:21:23 +00:00
black_compatibility@simple_cases__multiline_consecutive_open_parentheses_ignore.py.snap Add general support for parenthesized comments on expressions (#6485) 2023-08-15 18:59:18 +00:00
black_compatibility@simple_cases__power_op_spacing.py.snap Use reserved width to include line suffix measurement (#6901) 2023-08-30 08:07:11 +00:00
black_compatibility@simple_cases__remove_await_parens.py.snap Use reserved width to include line suffix measurement (#6901) 2023-08-30 08:07:11 +00:00
black_compatibility@simple_cases__remove_except_parens.py.snap Format raise statement (#5595) 2023-07-10 21:23:49 +02:00
black_compatibility@simple_cases__remove_for_brackets.py.snap Format lambda expression (#5806) 2023-07-19 11:47:56 +00:00
black_compatibility@simple_cases__return_annotation_brackets.py.snap Add general support for parenthesized comments on expressions (#6485) 2023-08-15 18:59:18 +00:00
black_compatibility@simple_cases__torture.py.snap Use reserved width to include line suffix measurement (#6901) 2023-08-30 08:07:11 +00:00
black_compatibility@simple_cases__trailing_comma_optional_parens3.py.snap Prefer expanding parenthesized expressions before operands 2023-07-11 14:07:39 +02:00
black_compatibility@simple_cases__trailing_commas_in_leading_parts.py.snap Use BestFits for non-fluent attribute chains (#6817) 2023-08-24 14:09:25 +02:00
black_compatibility@simple_cases__tupleassign.py.snap Format bytes string (#6166) 2023-07-31 10:46:40 +02:00
black_compatibility@simple_cases__whitespace.py.snap Update Black tests (#5438) 2023-06-30 06:32:50 +00:00
format@carriage_return__string.py.snap Normalize '\r' in string literals to '\n' 2023-06-30 10:13:23 +02:00
format@docstring.py.snap Add tab width option (#6848) 2023-08-26 12:29:58 +02:00
format@expression__annotated_assign.py.snap Format target: annotation = value? expressions (#5661) 2023-07-11 16:40:28 +02:00
format@expression__attribute.py.snap Format all attribute dot comments manually (#6825) 2023-08-25 03:50:56 +00:00
format@expression__binary.py.snap Avoid parenthesizing multiline strings in binary expressions (#6973) 2023-08-30 16:03:17 +02:00
format@expression__binary_implicit_string.py.snap Group binary operators with same precedence only (#7010) 2023-08-31 09:19:45 +02:00
format@expression__boolean_operation.py.snap Remove Comprehension priority (#6947) 2023-08-29 08:30:15 +02:00
format@expression__bytes.py.snap Add tab width option (#6848) 2023-08-26 12:29:58 +02:00
format@expression__call.py.snap Handle keyword comments between = and value (#6883) 2023-08-30 09:52:51 -04:00
format@expression__compare.py.snap Avoid omitting optional parentheses for argument-less parentheses (#6484) 2023-08-11 17:58:42 +00:00
format@expression__dict.py.snap Handle keyword comments between = and value (#6883) 2023-08-30 09:52:51 -04:00
format@expression__dict_comp.py.snap Expand parents whenever open-parenthesis comments are present (#6389) 2023-08-08 08:45:20 -04:00
format@expression__fstring.py.snap fix is_raw_string for multiple prefixes (#6865) 2023-08-25 09:58:26 +02:00
format@expression__generator_exp.py.snap Add general support for parenthesized comments on expressions (#6485) 2023-08-15 18:59:18 +00:00
format@expression__if.py.snap Don't "flatten" nested if expressions when formatting (#6996) 2023-08-30 04:11:58 +00:00
format@expression__lambda.py.snap Make Parameters an optional field on ExprLambda (#6669) 2023-08-18 15:34:54 +00:00
format@expression__list.py.snap Respect own-line leading comments before parenthesized nodes (#6820) 2023-08-25 00:18:05 -04:00
format@expression__list_comp.py.snap Tweak breaking groups for comprehensions (#6321) 2023-08-04 14:00:54 +00:00
format@expression__named_expr.py.snap Parenthesize NamedExpr if target breaks (#6714) 2023-08-21 16:29:26 +02:00
format@expression__set_comp.py.snap Avoid line break before for in comprehension if outer expression expands (#5912) 2023-07-20 10:07:22 +00:00
format@expression__slice.py.snap Improve slice formatting (#5922) 2023-07-20 15:05:18 +00:00
format@expression__split_empty_brackets.py.snap Avoid omitting optional parentheses for argument-less parentheses (#6484) 2023-08-11 17:58:42 +00:00
format@expression__starred.py.snap Fix comment formatting for yielded tuples (#6603) 2023-08-16 13:41:07 +00:00
format@expression__string.py.snap Add tab width option (#6848) 2023-08-26 12:29:58 +02:00
format@expression__tuple.py.snap Use reserved width to include line suffix measurement (#6901) 2023-08-30 08:07:11 +00:00
format@expression__unary.py.snap Maybe parenthesize long constants and names (#6816) 2023-08-24 09:47:57 +00:00
format@expression__unsplittable.py.snap Use BestFit layout even for attributes with a short name (#6872) 2023-08-25 17:47:02 +02:00
format@expression__yield.py.snap Use BestFits for non-fluent attribute chains (#6817) 2023-08-24 14:09:25 +02:00
format@expression__yield_from.py.snap Format ExprYield/ExprYieldFrom (#5921) 2023-07-21 12:07:51 +00:00
format@fmt_on_off__comments.py.snap Indent statements in suppressed ranges (#6507) 2023-08-15 08:00:35 +02:00
format@fmt_on_off__empty_file.py.snap fmt: off..on suppression comments (#6477) 2023-08-14 15:57:36 +00:00
format@fmt_on_off__fmt_off_docstring.py.snap Add tab width option (#6848) 2023-08-26 12:29:58 +02:00
format@fmt_on_off__form_feed.py.snap fmt: off..on suppression comments (#6477) 2023-08-14 15:57:36 +00:00
format@fmt_on_off__indent.py.snap Treat empty-line separated comments as trailing statement comments (#6999) 2023-08-31 20:55:05 +00:00
format@fmt_on_off__last_statement.py.snap fmt: off..on suppression comments (#6477) 2023-08-14 15:57:36 +00:00
format@fmt_on_off__mixed_space_and_tab.py.snap Treat empty-line separated comments as trailing statement comments (#6999) 2023-08-31 20:55:05 +00:00
format@fmt_on_off__newlines.py.snap Treat empty-line separated comments as trailing statement comments (#6999) 2023-08-31 20:55:05 +00:00
format@fmt_on_off__no_fmt_on.py.snap fmt: off..on suppression comments (#6477) 2023-08-14 15:57:36 +00:00
format@fmt_on_off__off_on_off_on.py.snap fmt: off..on suppression comments (#6477) 2023-08-14 15:57:36 +00:00
format@fmt_on_off__simple.py.snap fmt: off..on suppression comments (#6477) 2023-08-14 15:57:36 +00:00
format@fmt_on_off__trailing_comments.py.snap fmt: off..on suppression comments (#6477) 2023-08-14 15:57:36 +00:00
format@fmt_on_off__yapf.py.snap fmt: off..on suppression comments (#6477) 2023-08-14 15:57:36 +00:00
format@fmt_skip__decorators.py.snap Support fmt: skip for simple-statements and decorators (#6561) 2023-08-17 05:58:19 +00:00
format@fmt_skip__docstrings.py.snap Support fmt: skip for simple-statements and decorators (#6561) 2023-08-17 05:58:19 +00:00
format@fmt_skip__match.py.snap Format PatternMatchClass (#6860) 2023-08-25 19:03:37 +00:00
format@fmt_skip__or_else.py.snap Support fmt: skip on compound statements (#6593) 2023-08-17 06:05:41 +00:00
format@fmt_skip__parentheses.py.snap Support fmt: skip on compound statements (#6593) 2023-08-17 06:05:41 +00:00
format@fmt_skip__type_params.py.snap Fix fmt:skip for function with return type (#6733) 2023-08-21 17:45:23 +02:00
format@newlines.py.snap Treat empty-line separated comments as trailing statement comments (#6999) 2023-08-31 20:55:05 +00:00
format@parentheses__call_chains.py.snap Use reserved width to include line suffix measurement (#6901) 2023-08-30 08:07:11 +00:00
format@parentheses__nested.py.snap Add general support for parenthesized comments on expressions (#6485) 2023-08-15 18:59:18 +00:00
format@parentheses__opening_parentheses_comment_empty.py.snap Format PatternMatchSequence (#6676) 2023-08-23 00:44:33 +00:00
format@parentheses__opening_parentheses_comment_value.py.snap Handle open-parenthesis comments on match case (#6798) 2023-08-23 00:40:18 -04:00
format@skip_magic_trailing_comma.py.snap Add tab width option (#6848) 2023-08-26 12:29:58 +02:00
format@statement__ann_assign.py.snap Fix StmtAnnAssign formatting by mirroring StmtAssign (#5732) 2023-07-13 10:51:25 +00:00
format@statement__assert.py.snap Treat empty-line separated comments as trailing statement comments (#6999) 2023-08-31 20:55:05 +00:00
format@statement__assign.py.snap Add general support for parenthesized comments on expressions (#6485) 2023-08-15 18:59:18 +00:00
format@statement__aug_assign.py.snap Fix StmtAnnAssign formatting by mirroring StmtAssign (#5732) 2023-07-13 10:51:25 +00:00
format@statement__break.py.snap Add tests for skip magic trailing comma 2023-06-26 14:15:55 +02:00
format@statement__class_definition.py.snap Unset after_class_docstring state on every iteration (#7001) 2023-08-30 08:20:28 +02:00
format@statement__delete.py.snap Use reserved width to include line suffix measurement (#6901) 2023-08-30 08:07:11 +00:00
format@statement__ellipsis.pyi.snap Implement FormatPatternMatchValue (#6799) 2023-08-23 14:01:14 +00:00
format@statement__for.py.snap Omit tuple parentheses in for statements except when absolutely necessary (#6765) 2023-08-22 12:18:59 +02:00
format@statement__function.py.snap Treat empty-line separated comments as trailing statement comments (#6999) 2023-08-31 20:55:05 +00:00
format@statement__global.py.snap Break global and nonlocal statements over continuation lines (#6172) 2023-08-02 19:55:00 +00:00
format@statement__if.py.snap Fix formatter instability with half-indented comment (#6460) 2023-08-11 11:21:16 +00:00
format@statement__import.py.snap Allow up to two empty lines after top-level imports (#6777) 2023-08-22 12:27:40 -04:00
format@statement__import_from.py.snap Add trailing comma for single-element import-from groups (#6583) 2023-08-15 07:15:33 -04:00
format@statement__match.py.snap Handle keyword comments between = and value (#6883) 2023-08-30 09:52:51 -04:00
format@statement__nonlocal.py.snap Break global and nonlocal statements over continuation lines (#6172) 2023-08-02 19:55:00 +00:00
format@statement__raise.py.snap Add general support for parenthesized comments on expressions (#6485) 2023-08-15 18:59:18 +00:00
format@statement__return.py.snap Use optional parentheses for tuples in return statements (#6875) 2023-08-29 08:30:05 +02:00
format@statement__return_annotation.py.snap Add general support for parenthesized comments on expressions (#6485) 2023-08-15 18:59:18 +00:00
format@statement__top_level.py.snap Use one line between top-level items if formatting a stub file (#6501) 2023-08-15 09:33:57 +02:00
format@statement__top_level.pyi.snap Format function and class definitions into a single line if its body is an ellipsis (#6592) 2023-08-21 09:02:23 +02:00
format@statement__try.py.snap Use reserved width to include line suffix measurement (#6901) 2023-08-30 08:07:11 +00:00
format@statement__type_alias.py.snap Add formatting of type alias statements (#6162) 2023-08-02 20:40:32 +00:00
format@statement__while.py.snap Use reserved width to include line suffix measurement (#6901) 2023-08-30 08:07:11 +00:00
format@statement__with.py.snap Improve with statement comment handling and expression breaking (#6621) 2023-08-18 03:30:38 +00:00
format@tab_width.py.snap Add tab width option (#6848) 2023-08-26 12:29:58 +02:00
format@trailing_comments.py.snap Use reserved width to include line suffix measurement (#6901) 2023-08-30 08:07:11 +00:00
format@trivia.py.snap Add tests for skip magic trailing comma 2023-06-26 14:15:55 +02:00