A basic StmtAssign formatter and better dummies for expressions (#4938)

* A basic StmtAssign formatter and better dummies for expressions

The goal of this PR was formatting StmtAssign since many nodes in the black tests (and in python in general) are after an assignment. This caused unstable formatting: The spacing of power op spacing depends on the type of the two involved expressions, but each expression was formatted as dummy string and re-parsed as a ExprName, so in the second round the different rules of ExprName were applied, causing unstable formatting.

This PR does not necessarily bring us closer to black's style, but it unlocks a good porting of black's test suite and is a basis for implementing the Expr nodes.

* fmt

* Review
This commit is contained in:
konstin 2023-06-08 12:20:25 +02:00 committed by GitHub
parent 651d89794c
commit 23abad0bd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
62 changed files with 1291 additions and 1023 deletions

View file

@ -164,6 +164,36 @@ impl Format<PyFormatContext<'_>> for NotYetImplemented {
}
}
pub(crate) struct NotYetImplementedCustomText(NodeKind, String);
/// Formats a placeholder for nodes that have not yet been implemented
pub(crate) fn not_yet_implemented_custom_text<'a, T>(
node: T,
text: impl AsRef<str>,
) -> NotYetImplementedCustomText
where
T: Into<AnyNodeRef<'a>>,
{
NotYetImplementedCustomText(node.into().kind(), text.as_ref().to_string())
}
impl Format<PyFormatContext<'_>> for NotYetImplementedCustomText {
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
f.write_element(FormatElement::Tag(Tag::StartVerbatim(
tag::VerbatimKind::Verbatim {
length: self.1.text_len(),
},
)))?;
f.write_element(FormatElement::DynamicText {
text: Box::from(self.1.clone()),
})?;
f.write_element(FormatElement::Tag(Tag::EndVerbatim))?;
Ok(())
}
}
pub(crate) struct VerbatimText(TextRange);
#[allow(unused)]
@ -250,11 +280,15 @@ NOT_YET_IMPLEMENTED_StmtIf
let formatted_code = printed.as_code();
let reformatted = format_module(formatted_code).unwrap_or_else(|err| {
panic!(
"Formatted code resulted introduced a syntax error {err:#?}. Code:\n{formatted_code}"
)
});
let reformatted = match format_module(formatted_code) {
Ok(reformatted) => reformatted,
Err(err) => {
panic!(
"Expected formatted code to be valid syntax: {err}:\
\n---\n{formatted_code}---\n",
);
}
};
if reformatted.as_code() != formatted_code {
let diff = TextDiff::from_lines(formatted_code, reformatted.as_code())
@ -263,13 +297,16 @@ NOT_YET_IMPLEMENTED_StmtIf
.to_string();
panic!(
r#"Reformatting the formatted code a second time resulted in formatting changes.
{diff}
---
{diff}---
Formatted once:
{formatted_code}
---
{formatted_code}---
Formatted twice:
{}"#,
---
{}---"#,
reformatted.as_code()
);
}