Use space separator before parenthesiszed expressions in comprehensions with leading comments. (#12282)

This commit is contained in:
Micha Reiser 2024-07-11 22:38:12 +02:00 committed by GitHub
parent d0298dc26d
commit bd01004a42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 274 additions and 6 deletions

View file

@ -105,3 +105,66 @@ aaaaaaaaaaaaaaaaaaaaa = [
# Parenthesized targets and iterators. # Parenthesized targets and iterators.
[x for (x) in y] [x for (x) in y]
[x for x in (y)] [x for x in (y)]
# Leading expression comments:
y = [
a
for (
# comment
a
) in (
# comment
x
)
if (
# asdasd
"askldaklsdnmklasmdlkasmdlkasmdlkasmdasd"
!= "as,mdnaskldmlkasdmlaksdmlkasdlkasdm"
and "zxcm,.nzxclm,zxnckmnzxckmnzxczxc" != "zxcasdasdlmnasdlknaslkdnmlaskdm"
)
if (
# comment
x
)
]
# Tuple target:
y = [
a
for
# comment
a, b
in x
if True
]
y = [
a
for (
# comment
a, b
)
in x
if True
]
y = [
a
for
# comment
a
in
# comment
x
if
# asdasd
"askldaklsdnmklasmdlkasmdlkasmdlkasmdasd"
!= "as,mdnaskldmlkasdmlaksdmlkasdlkasdm"
and "zxcm,.nzxclm,zxnckmnzxckmnzxczxc" != "zxcasdasdlmnasdlknaslkdnmlaskdm"
if
# comment
x
]

View file

@ -5,18 +5,47 @@ use ruff_text_size::{Ranged, TextRange};
use crate::comments::{leading_comments, trailing_comments}; use crate::comments::{leading_comments, trailing_comments};
use crate::expression::expr_tuple::TupleParentheses; use crate::expression::expr_tuple::TupleParentheses;
use crate::expression::parentheses::is_expression_parenthesized;
use crate::prelude::*; use crate::prelude::*;
use crate::preview::is_comprehension_leading_expression_comments_same_line_enabled;
#[derive(Default)] #[derive(Default)]
pub struct FormatComprehension; pub struct FormatComprehension;
impl FormatNodeRule<Comprehension> for FormatComprehension { impl FormatNodeRule<Comprehension> for FormatComprehension {
fn fmt_fields(&self, item: &Comprehension, f: &mut PyFormatter) -> FormatResult<()> { fn fmt_fields(&self, item: &Comprehension, f: &mut PyFormatter) -> FormatResult<()> {
struct Spacer<'a>(&'a Expr); struct Spacer<'a> {
expression: &'a Expr,
preserve_parentheses: bool,
}
impl Format<PyFormatContext<'_>> for Spacer<'_> { impl Format<PyFormatContext<'_>> for Spacer<'_> {
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> { fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
if f.context().comments().has_leading(self.0) { let has_leading_comments = f.context().comments().has_leading(self.expression);
// Don't add a soft line break for parenthesized expressions with a leading comment.
// The comments are rendered **inside** the parentheses and adding a softline break
// unnecessarily forces the parentheses to be on their own line.
// ```python
// y = [
// ...
// if
// (
// # See how the `(` gets forced on its own line? We don't want that.
// ...
// )
// ]
// ```
let will_be_parenthesized =
is_comprehension_leading_expression_comments_same_line_enabled(f.context())
&& self.preserve_parentheses
&& is_expression_parenthesized(
self.expression.into(),
f.context().comments().ranges(),
f.context().source(),
);
if has_leading_comments && !will_be_parenthesized {
soft_line_break_or_space().fmt(f) soft_line_break_or_space().fmt(f)
} else { } else {
space().fmt(f) space().fmt(f)
@ -68,13 +97,19 @@ impl FormatNodeRule<Comprehension> for FormatComprehension {
[ [
token("for"), token("for"),
trailing_comments(before_target_comments), trailing_comments(before_target_comments),
Spacer(target), Spacer {
expression: target,
preserve_parentheses: !target.is_tuple_expr()
},
ExprTupleWithoutParentheses(target), ExprTupleWithoutParentheses(target),
in_spacer, in_spacer,
leading_comments(before_in_comments), leading_comments(before_in_comments),
token("in"), token("in"),
trailing_comments(trailing_in_comments), trailing_comments(trailing_in_comments),
Spacer(iter), Spacer {
expression: iter,
preserve_parentheses: true
},
iter.format(), iter.format(),
] ]
)?; )?;
@ -99,7 +134,10 @@ impl FormatNodeRule<Comprehension> for FormatComprehension {
leading_comments(own_line_if_comments), leading_comments(own_line_if_comments),
token("if"), token("if"),
trailing_comments(end_of_line_if_comments), trailing_comments(end_of_line_if_comments),
Spacer(if_case), Spacer {
expression: if_case,
preserve_parentheses: true
},
if_case.format(), if_case.format(),
)); ));

View file

@ -22,3 +22,10 @@ pub(crate) fn is_f_string_formatting_enabled(context: &PyFormatContext) -> bool
pub(crate) fn is_with_single_item_pre_39_enabled(context: &PyFormatContext) -> bool { pub(crate) fn is_with_single_item_pre_39_enabled(context: &PyFormatContext) -> bool {
context.is_preview() context.is_preview()
} }
/// See [#12282](https://github.com/astral-sh/ruff/pull/12282).
pub(crate) fn is_comprehension_leading_expression_comments_same_line_enabled(
context: &PyFormatContext,
) -> bool {
context.is_preview()
}

View file

@ -111,6 +111,69 @@ aaaaaaaaaaaaaaaaaaaaa = [
# Parenthesized targets and iterators. # Parenthesized targets and iterators.
[x for (x) in y] [x for (x) in y]
[x for x in (y)] [x for x in (y)]
# Leading expression comments:
y = [
a
for (
# comment
a
) in (
# comment
x
)
if (
# asdasd
"askldaklsdnmklasmdlkasmdlkasmdlkasmdasd"
!= "as,mdnaskldmlkasdmlaksdmlkasdlkasdm"
and "zxcm,.nzxclm,zxnckmnzxckmnzxczxc" != "zxcasdasdlmnasdlknaslkdnmlaskdm"
)
if (
# comment
x
)
]
# Tuple target:
y = [
a
for
# comment
a, b
in x
if True
]
y = [
a
for (
# comment
a, b
)
in x
if True
]
y = [
a
for
# comment
a
in
# comment
x
if
# asdasd
"askldaklsdnmklasmdlkasmdlkasmdlkasmdasd"
!= "as,mdnaskldmlkasdmlaksdmlkasdlkasdm"
and "zxcm,.nzxclm,zxnckmnzxckmnzxczxc" != "zxcasdasdlmnasdlknaslkdnmlaskdm"
if
# comment
x
]
``` ```
## Output ## Output
@ -254,7 +317,104 @@ aaaaaaaaaaaaaaaaaaaaa = [
# Parenthesized targets and iterators. # Parenthesized targets and iterators.
[x for (x) in y] [x for (x) in y]
[x for x in (y)] [x for x in (y)]
# Leading expression comments:
y = [
a
for
(
# comment
a
) in
(
# comment
x
)
if
(
# asdasd
"askldaklsdnmklasmdlkasmdlkasmdlkasmdasd"
!= "as,mdnaskldmlkasdmlaksdmlkasdlkasdm"
and "zxcm,.nzxclm,zxnckmnzxckmnzxczxc" != "zxcasdasdlmnasdlknaslkdnmlaskdm"
)
if
(
# comment
x
)
]
# Tuple target:
y = [
a
for
# comment
a, b in x
if True
]
y = [
a
for (
# comment
a,
b,
) in x
if True
]
y = [
a
for
# comment
a in
# comment
x
if
# asdasd
"askldaklsdnmklasmdlkasmdlkasmdlkasmdasd" != "as,mdnaskldmlkasdmlaksdmlkasdlkasdm"
and "zxcm,.nzxclm,zxnckmnzxckmnzxczxc" != "zxcasdasdlmnasdlknaslkdnmlaskdm"
if
# comment
x
]
``` ```
## Preview changes
```diff
--- Stable
+++ Preview
@@ -142,24 +142,20 @@
# Leading expression comments:
y = [
a
- for
- (
+ for (
# comment
a
- ) in
- (
+ ) in (
# comment
x
)
- if
- (
+ if (
# asdasd
"askldaklsdnmklasmdlkasmdlkasmdlkasmdasd"
!= "as,mdnaskldmlkasdmlaksdmlkasdlkasdm"
and "zxcm,.nzxclm,zxnckmnzxckmnzxczxc" != "zxcasdasdlmnasdlknaslkdnmlaskdm"
)
- if
- (
+ if (
# comment
x
)
```