mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 05:25:17 +00:00
Preserve parentheses around left side of binary expression
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary This PR fixes an issue where the binary expression formatting removed parentheses around the left hand side of an expression. <!-- What's the purpose of the change? What does it do, and why? --> ## Test Plan I added a new regression test and re-ran the ecosystem check. It brings down the `check-formatter-stability` output from a 3.4MB file down to 900KB. <!-- How was it tested? -->
This commit is contained in:
parent
ae25638b0b
commit
9c2a75284b
5 changed files with 41 additions and 19 deletions
|
@ -205,3 +205,9 @@ if (
|
|||
# Unstable formatting in https://github.com/realtyem/synapse-unraid/blob/unraid_develop/synapse/handlers/presence.py
|
||||
for user_id in set(target_user_ids) - {u.user_id for u in updates}:
|
||||
updates.append(UserPresenceState.default(user_id))
|
||||
|
||||
# Keeps parenthesized left hand sides
|
||||
(
|
||||
log(self.price / self.strike)
|
||||
+ (self.risk_free - self.div_cont + 0.5 * (self.sigma**2)) * self.exp_time
|
||||
) / self.sigmaT
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
use crate::comments::{trailing_comments, trailing_node_comments, Comments};
|
||||
use crate::expression::binary_like::{BinaryLayout, FormatBinaryLike};
|
||||
use crate::expression::parentheses::{
|
||||
default_expression_needs_parentheses, NeedsParentheses, Parenthesize,
|
||||
default_expression_needs_parentheses, is_expression_parenthesized, NeedsParentheses,
|
||||
Parenthesize,
|
||||
};
|
||||
use crate::expression::Parentheses;
|
||||
use crate::prelude::*;
|
||||
use crate::FormatNodeRule;
|
||||
use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule, FormatRuleWithOptions};
|
||||
use ruff_python_ast::node::AstNode;
|
||||
use rustpython_parser::ast::{
|
||||
Constant, Expr, ExprAttribute, ExprBinOp, ExprConstant, ExprUnaryOp, Operator, UnaryOp,
|
||||
};
|
||||
|
@ -44,9 +46,18 @@ impl<'ast> FormatBinaryLike<'ast> for ExprBinOp {
|
|||
fn fmt_default(&self, f: &mut PyFormatter<'ast, '_>) -> FormatResult<()> {
|
||||
let comments = f.context().comments().clone();
|
||||
|
||||
let format_inner = format_with(|f| {
|
||||
let binary_chain: SmallVec<[&ExprBinOp; 4]> =
|
||||
iter::successors(Some(self), |parent| parent.left.as_bin_op_expr()).collect();
|
||||
let format_inner = format_with(|f: &mut PyFormatter| {
|
||||
let source = f.context().contents();
|
||||
let binary_chain: SmallVec<[&ExprBinOp; 4]> = iter::successors(Some(self), |parent| {
|
||||
parent.left.as_bin_op_expr().and_then(|bin_expression| {
|
||||
if is_expression_parenthesized(bin_expression.as_any_node_ref(), source) {
|
||||
None
|
||||
} else {
|
||||
Some(bin_expression)
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
// SAFETY: `binary_chain` is guaranteed not to be empty because it always contains the current expression.
|
||||
let left_most = binary_chain.last().unwrap();
|
||||
|
|
|
@ -274,20 +274,11 @@ last_call()
|
|||
Name
|
||||
None
|
||||
True
|
||||
@@ -24,40 +24,46 @@
|
||||
1 >> v2
|
||||
1 % finished
|
||||
1 + v2 - v3 * 4 ^ 5**v6 / 7 // 8
|
||||
-((1 + v2) - (v3 * 4)) ^ (((5**v6) / 7) // 8)
|
||||
+(1 + v2 - (v3 * 4)) ^ (5**v6 / 7 // 8)
|
||||
not great
|
||||
~great
|
||||
+value
|
||||
@@ -31,33 +31,39 @@
|
||||
-1
|
||||
~int and not v1 ^ 123 + v2 | True
|
||||
-(~int) and (not ((v1 ^ (123 + v2)) | True))
|
||||
(~int) and (not ((v1 ^ (123 + v2)) | True))
|
||||
-+(really ** -(confusing ** ~(operator**-precedence)))
|
||||
+(~int) and (not (v1 ^ (123 + v2) | True))
|
||||
++really ** -confusing ** ~operator**-precedence
|
||||
flags & ~select.EPOLLIN and waiters.write_task is not None
|
||||
-lambda arg: None
|
||||
|
@ -650,13 +641,13 @@ v1 << 2
|
|||
1 >> v2
|
||||
1 % finished
|
||||
1 + v2 - v3 * 4 ^ 5**v6 / 7 // 8
|
||||
(1 + v2 - (v3 * 4)) ^ (5**v6 / 7 // 8)
|
||||
((1 + v2) - (v3 * 4)) ^ (((5**v6) / 7) // 8)
|
||||
not great
|
||||
~great
|
||||
+value
|
||||
-1
|
||||
~int and not v1 ^ 123 + v2 | True
|
||||
(~int) and (not (v1 ^ (123 + v2) | True))
|
||||
(~int) and (not ((v1 ^ (123 + v2)) | True))
|
||||
+really ** -confusing ** ~operator**-precedence
|
||||
flags & ~select.EPOLLIN and waiters.write_task is not None
|
||||
lambda x: True
|
||||
|
|
|
@ -211,6 +211,12 @@ if (
|
|||
# Unstable formatting in https://github.com/realtyem/synapse-unraid/blob/unraid_develop/synapse/handlers/presence.py
|
||||
for user_id in set(target_user_ids) - {u.user_id for u in updates}:
|
||||
updates.append(UserPresenceState.default(user_id))
|
||||
|
||||
# Keeps parenthesized left hand sides
|
||||
(
|
||||
log(self.price / self.strike)
|
||||
+ (self.risk_free - self.div_cont + 0.5 * (self.sigma**2)) * self.exp_time
|
||||
) / self.sigmaT
|
||||
```
|
||||
|
||||
## Output
|
||||
|
@ -468,6 +474,12 @@ for user_id in set(
|
|||
target_user_ids
|
||||
) - {NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}:
|
||||
updates.append(UserPresenceState.default(user_id))
|
||||
|
||||
# Keeps parenthesized left hand sides
|
||||
(
|
||||
log(self.price / self.strike)
|
||||
+ (self.risk_free - self.div_cont + 0.5 * (self.sigma**2)) * self.exp_time
|
||||
) / self.sigmaT
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -257,8 +257,10 @@ if aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa & (
|
|||
pass
|
||||
|
||||
if (
|
||||
not aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
not (
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
)
|
||||
& aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
):
|
||||
pass
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue