-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Split implicit concatenated strings before binary expressions #7145
Conversation
Current dependencies on/for this PR:
This comment was auto-generated by Graphite. |
7f88fc6
to
8251e70
Compare
8251e70
to
863bbba
Compare
PR Check ResultsEcosystem✅ ecosystem check detected no changes. |
This comment was marked as outdated.
This comment was marked as outdated.
} | ||
|
||
pub(crate) enum FormatTrailingComments<'a> { | ||
Node(AnyNodeRef<'a>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the Node
variance because this PR removes the last trailing_node_comments
reference
use ruff_python_ast::Operator; | ||
|
||
#[derive(Copy, Clone)] | ||
pub struct FormatOperator; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved this out of the bin_expr
formatting because it is also used in augmented assign and it removes the size of the bin_expr
file a bit. The code itself is unchanged.
@@ -168,10 +168,9 @@ pub fn format_node<'a>( | |||
} | |||
|
|||
/// Public function for generating a printable string of the debug comments. | |||
pub fn pretty_comments(formatted: &Formatted<PyFormatContext>, source: &str) -> String { | |||
let comments = formatted.context().comments(); | |||
pub fn pretty_comments(root: &Mod, comment_ranges: &CommentRanges, source: &str) -> String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not strictly related to the PR but I ran into situations where I missed to format some comments but was unable to see the comments in the playground because it extracted them from the formatted output...
This change now allows to see the comments even if the formatting itself fails.
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbb" | ||
"cccccccccccccccccccccccccc" % aaaaaaaaaaaa | ||
+ x | ||
"cccccccccccccccccccccccccc" % aaaaaaaaaaaa + x | ||
) | ||
|
||
( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add support for compare expressions in a separate PR
let chain = BinaryChain::from_binary_expression(item, &comments, f.context().source()); | ||
|
||
let source = f.context().source(); | ||
let mut string_operands = chain |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add support for f-strings in a separate PR
@@ -27,120 +29,188 @@ pub struct FormatExprBinOp; | |||
impl FormatNodeRule<ExprBinOp> for FormatExprBinOp { | |||
fn fmt_fields(&self, item: &ExprBinOp, f: &mut PyFormatter) -> FormatResult<()> { | |||
let comments = f.context().comments().clone(); | |||
|
|||
match Self::layout(item, f.context()) { | |||
BinOpLayout::LeftString(expression) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The LeftString
was a "cheap" implementation of the new formatting logic that only supported implicit concatenated strings at the left of a binary expression. The new formatting supports implicit concatenated strings in arbitrary positions.
#[allow(unsafe_code)] | ||
unsafe { | ||
// SAFETY: `BinaryChainSlice` has the same layout as a slice because it uses `repr(transparent)` | ||
&*(slice as *const [OperandOrOperator<'a>] as *const BinaryChainSlice<'a>) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the same layout is necessary to implement Deref
on BinaryChain
863bbba
to
a5c514d
Compare
a5c514d
to
dc12ba4
Compare
I moved the formatting to its own file as preparation for re-using it for |
CodSpeed Performance ReportMerging #7145 will degrade performances by 2.44%Comparing Summary
Benchmarks breakdown
|
I doubt that ;) |
668d1c4
to
8f4ae4c
Compare
8f4ae4c
to
c2d42e9
Compare
## Summary This PR implements the logic for breaking implicit concatenated strings before compare expressions by building on top of #7145 The main change is a new `BinaryLike` enum that has the `BinaryExpression` and `CompareExpression` variants. Supporting both variants requires some downstream changes but doesn't introduce any new concepts. ## Test Plan I added a few more tests. The compatibility improvements are minor but we now perfectly match black on twine 🥳 **PR** | project | similarity index | total files | changed files | |--------------|------------------:|------------------:|------------------:| | cpython | 0.76083 | 1789 | 1632 | | django | 0.99966 | 2760 | 58 | | transformers | 0.99928 | 2587 | 454 | | **twine** | 1.00000 | 33 | 0 | <-- improved | typeshed | 0.99978 | 3496 | 2173 | | **warehouse** | 0.99824 | 648 | 22 | <-- improved | zulip | 0.99948 | 1437 | 28 | **Base** | project | similarity index | total files | changed files | |--------------|------------------:|------------------:|------------------:| | cpython | 0.76083 | 1789 | 1633 | | django | 0.99966 | 2760 | 58 | | transformers | 0.99928 | 2587 | 454 | | twine | 0.99982 | 33 | 1 | | typeshed | 0.99978 | 3496 | 2173 | | warehouse | 0.99823 | 648 | 23 | | zulip | 0.99948 | 1437 | 28 |
Summary
This PR improves Black compatibility by breaking implicit concatenated string before any binary expression.
You can see how Black inserts line breaks between the implicit concatenated string parts but it keeps the binary expression operators and operands on the same line.
The challenge with implementing this formatting is that it is necessary that the outermost group is the group around the implicit concatenated strings but this doesn't match our AST structure: The strings are leaf nodes in the AST. See the tree for a very basic example
a + 'b' 'c'
The existing implementation used a custom layout for when the implicit concatenated string is on the left side but it isn't able to handle implicit concatenated strings on the right or in nested binary expressions.
This PR solves this by flattening the binary expression. From the code documentation
The flat representation allows to first split the binary expression by implicit concatenated strings and only then, operator by operator based on the operator precedence.
Test Plan
I added new tests, reviewed that the changes now match Black's formatting.
The PR improves the black compatibility
PR
Base