Fix a number of formatter errors from the cpython repository (#5089)

## Summary

This fixes a number of problems in the formatter that showed up with
various files in the [cpython](https://github.com/python/cpython)
repository. These problems surfaced as unstable formatting and invalid
code. This is not the entirety of problems discovered through cpython,
but a big enough chunk to separate it. Individual fixes are generally
individual commits. They were discovered with #5055, which i update as i
work through the output

## Test Plan

I added regression tests with links to cpython for each entry, except
for the two stubs that also got comment stubs since they'll be
implemented properly later.
This commit is contained in:
konstin 2023-06-15 13:24:14 +02:00 committed by GitHub
parent 097823b56d
commit 66089e1a2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 234 additions and 23 deletions

View file

@ -39,6 +39,22 @@ impl FormatNodeRule<ExprConstant> for FormatExprConstant {
}
}
}
fn fmt_dangling_comments(
&self,
_node: &ExprConstant,
_f: &mut PyFormatter,
) -> FormatResult<()> {
// TODO(konstin): Reactivate when string formatting works, currently a source of unstable
// formatting, e.g.:
// magic_methods = (
// "enter exit "
// # we added divmod and rdivmod here instead of numerics
// # because there is no idivmod
// "divmod rdivmod neg pos abs invert "
// )
Ok(())
}
}
impl NeedsParentheses for ExprConstant {

View file

@ -18,6 +18,17 @@ impl FormatNodeRule<ExprDict> for FormatExprDict {
)]
)
}
fn fmt_dangling_comments(&self, _node: &ExprDict, _f: &mut PyFormatter) -> FormatResult<()> {
// TODO(konstin): Reactivate when string formatting works, currently a source of unstable
// formatting, e.g.
// ```python
// coverage_ignore_c_items = {
// # 'cfunction': [...]
// }
// ```
Ok(())
}
}
impl NeedsParentheses for ExprDict {

View file

@ -1,4 +1,4 @@
use crate::comments::{dangling_comments, Comments};
use crate::comments::{dangling_comments, CommentTextPosition, Comments};
use crate::expression::parentheses::{
default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
};
@ -18,6 +18,39 @@ impl FormatNodeRule<ExprList> for FormatExprList {
ctx: _,
} = item;
let comments = f.context().comments().clone();
let dangling = comments.dangling_comments(item.into());
// The empty list is special because there can be dangling comments, and they can be in two
// positions:
// ```python
// a3 = [ # end-of-line
// # own line
// ]
// ```
// In all other cases comments get assigned to a list element
if elts.is_empty() {
let end_of_line_split = dangling
.partition_point(|comment| comment.position() == CommentTextPosition::EndOfLine);
debug_assert!(dangling[end_of_line_split..]
.iter()
.all(|comment| comment.position() == CommentTextPosition::OwnLine));
return write!(
f,
[group(&format_args![
text("["),
dangling_comments(&dangling[..end_of_line_split]),
soft_block_indent(&dangling_comments(&dangling[end_of_line_split..])),
text("]")
])]
);
}
debug_assert!(
dangling.is_empty(),
"A non-empty expression list has dangling comments"
);
let items = format_with(|f| {
let mut iter = elts.iter();
@ -36,14 +69,10 @@ impl FormatNodeRule<ExprList> for FormatExprList {
Ok(())
});
let comments = f.context().comments().clone();
let dangling = comments.dangling_comments(item.into());
write!(
f,
[group(&format_args![
text("["),
dangling_comments(dangling),
soft_block_indent(&items),
text("]")
])]