Skip to content

Commit

Permalink
Format comment before parameter default correctly (#7870)
Browse files Browse the repository at this point in the history
**Summary** Handle comment before the default values of function
parameters correctly by inserting a line break instead of space after
the equals sign where required.

```python
def f(
    a = # parameter trailing comment; needs line break
    1,
    b =
    # default leading comment; needs line break
    2,
    c = ( # the default leading can only be end-of-line with parentheses; no line break
        3
    ),
    d = (
        # own line leading comment with parentheses; no line break
        4
    )
)
```

Fixes #7603

**Test Plan** Added the different cases and one more complex case as
fixtures.
  • Loading branch information
konstin authored Oct 12, 2023
1 parent cb06b79 commit 3944c42
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,29 @@ def test():
#comment
except ImportError:
pass

# https://github.com/astral-sh/ruff/issues/7603
def default_arg_comments(
a: str = #a
"a",
b: str =
#b
"b",
c: str =( #c
"c"
),
d: str =(
#d
"d"
)
):
print(a, b, c, d)

def default_arg_comments2(#
x: int#=
= #
#
123#
#
):
print(x)
48 changes: 47 additions & 1 deletion crates/ruff_python_formatter/src/other/parameter_with_default.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use ruff_formatter::write;
use ruff_python_ast::ParameterWithDefault;
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
use ruff_text_size::{Ranged, TextRange};

use crate::prelude::*;

Expand All @@ -18,7 +20,51 @@ impl FormatNodeRule<ParameterWithDefault> for FormatParameterWithDefault {

if let Some(default) = default {
let space = parameter.annotation.is_some().then_some(space());
write!(f, [space, token("="), space, group(&default.format())])?;
// ```python
// def f(
// a = # parameter trailing comment; needs line break
// 1,
// b =
// # default leading comment; needs line break
// 2,
// c = ( # the default leading can only be end-of-line with parentheses; no line break
// 3
// ),
// d = (
// # own line leading comment with parentheses; no line break
// 4
// )
// )
// ```
let needs_line_break_trailing = f.context().comments().has_trailing(parameter);
let default_first_comment = f.context().comments().leading(default.as_ref()).first();
let needs_line_break_leading = default_first_comment.is_some_and(|default_leading_comment| {
let mut tokenizer = SimpleTokenizer::new(
f.context().source(),
TextRange::new(parameter.end(), default_leading_comment.start()),
)
.skip_trivia()
.skip_while(|token| token.kind == SimpleTokenKind::RParen);
let equals = tokenizer.next();
debug_assert!(equals.is_some_and(|token| token.kind == SimpleTokenKind::Equals));
let lparens = tokenizer.next();
debug_assert!(lparens
.as_ref()
.map_or(true, |token| token.kind == SimpleTokenKind::LParen));
lparens.is_none()
});
let needs_line_break = needs_line_break_trailing || needs_line_break_leading;

write!(
f,
[
space,
token("="),
(!needs_line_break).then_some(space),
needs_line_break.then_some(hard_line_break()),
group(&default.format())
]
)?;
}

Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,32 @@ try:
#comment
except ImportError:
pass

# https://github.com/astral-sh/ruff/issues/7603
def default_arg_comments(
a: str = #a
"a",
b: str =
#b
"b",
c: str =( #c
"c"
),
d: str =(
#d
"d"
)
):
print(a, b, c, d)

def default_arg_comments2(#
x: int#=
= #
#
123#
#
):
print(x)
```

## Output
Expand Down Expand Up @@ -940,6 +966,33 @@ try:
# comment
except ImportError:
pass


# https://github.com/astral-sh/ruff/issues/7603
def default_arg_comments(
a: str = # a
"a",
b: str =
# b
"b",
c: str = ( # c
"c"
),
d: str = (
# d
"d"
),
):
print(a, b, c, d)


def default_arg_comments2( #
x: int = # = #
#
123, #
#
):
print(x)
```


Expand Down

0 comments on commit 3944c42

Please sign in to comment.