mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 11:59:35 +00:00
Format comment before parameter default correctly (#7870)
**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.
This commit is contained in:
parent
cb06b7956c
commit
3944c42d4c
3 changed files with 126 additions and 1 deletions
|
@ -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::*;
|
||||
|
||||
|
@ -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(())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue