mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:10:09 +00:00
Formatter: Add EmptyWithDanglingComments helper (#5951)
**Summary** Add a `EmptyWithDanglingComments` format helper that formats comments inside empty parentheses, brackets or curly braces. Previously, this was implemented separately, and partially incorrectly, for each use case. Empty `()`, `[]` and `{}` are special because there can be dangling comments, and they can be in two positions: ```python x = [ # end-of-line # own line ] ``` These comments are dangling because they can't be assigned to any element inside as they would in all other cases. **Test Plan** Added a regression test. 145 (from previously 149) instances of unstable formatting remaining. ``` $ cargo run --bin ruff_dev --release -- format-dev --stability-check --error-file formatter-ecosystem-errors.txt --multi-project target/checkouts > formatter-ecosystem-progress.txt $ rg "Unstable formatting" target/formatter-ecosystem-errors.txt | wc -l 145 ```
This commit is contained in:
parent
f886b58c92
commit
46f8961292
9 changed files with 94 additions and 56 deletions
|
@ -1,6 +1,7 @@
|
|||
use ruff_text_size::{TextRange, TextSize};
|
||||
use rustpython_parser::ast::Ranged;
|
||||
|
||||
use crate::comments::{dangling_comments, SourceComment};
|
||||
use ruff_formatter::{format_args, write, Argument, Arguments};
|
||||
use ruff_python_trivia::{
|
||||
lines_after, skip_trailing_trivia, SimpleToken, SimpleTokenKind, SimpleTokenizer,
|
||||
|
@ -323,6 +324,57 @@ impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Format comments inside empty parentheses, brackets or curly braces.
|
||||
///
|
||||
/// Empty `()`, `[]` and `{}` are special because there can be dangling comments, and they can be in
|
||||
/// two positions:
|
||||
/// ```python
|
||||
/// x = [ # end-of-line
|
||||
/// # own line
|
||||
/// ]
|
||||
/// ```
|
||||
/// These comments are dangling because they can't be assigned to any element inside as they would
|
||||
/// in all other cases.
|
||||
pub(crate) fn empty_parenthesized_with_dangling_comments(
|
||||
opening: StaticText,
|
||||
comments: &[SourceComment],
|
||||
closing: StaticText,
|
||||
) -> EmptyWithDanglingComments {
|
||||
EmptyWithDanglingComments {
|
||||
opening,
|
||||
comments,
|
||||
closing,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct EmptyWithDanglingComments<'a> {
|
||||
opening: StaticText,
|
||||
comments: &'a [SourceComment],
|
||||
closing: StaticText,
|
||||
}
|
||||
|
||||
impl<'ast> Format<PyFormatContext<'ast>> for EmptyWithDanglingComments<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<PyFormatContext>) -> FormatResult<()> {
|
||||
let end_of_line_split = self
|
||||
.comments
|
||||
.partition_point(|comment| comment.line_position().is_end_of_line());
|
||||
debug_assert!(self.comments[end_of_line_split..]
|
||||
.iter()
|
||||
.all(|comment| comment.line_position().is_own_line()));
|
||||
write!(
|
||||
f,
|
||||
[group(&format_args![
|
||||
self.opening,
|
||||
// end-of-line comments
|
||||
dangling_comments(&self.comments[..end_of_line_split]),
|
||||
// own line comments, which need to be indented
|
||||
soft_block_indent(&dangling_comments(&self.comments[end_of_line_split..])),
|
||||
self.closing
|
||||
])]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rustpython_parser::ast::ModModule;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue