-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
18 changed files
with
638 additions
and
187 deletions.
There are no files selected for viewing
27 changes: 27 additions & 0 deletions
27
crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/binary_expression.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
(aaaaaaaa | ||
+ # trailing operator comment | ||
b # trailing right comment | ||
) | ||
|
||
|
||
(aaaaaaaa # trailing left comment | ||
+ # trailing operator comment | ||
# leading right comment | ||
b | ||
) | ||
|
||
|
||
# Black breaks the right side first for the following expressions: | ||
aaaaaaaaaaaaaa + caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaal(argument1, argument2, argument3) | ||
aaaaaaaaaaaaaa + [bbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc, dddddddddddddddd, eeeeeee] | ||
aaaaaaaaaaaaaa + (bbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc, dddddddddddddddd, eeeeeee) | ||
aaaaaaaaaaaaaa + { key1:bbbbbbbbbbbbbbbbbbbbbb, key2: ccccccccccccccccccccc, key3: dddddddddddddddd, key4: eeeeeee } | ||
aaaaaaaaaaaaaa + { bbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc, dddddddddddddddd, eeeeeee } | ||
aaaaaaaaaaaaaa + [a for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ] | ||
aaaaaaaaaaaaaa + (a for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ) | ||
aaaaaaaaaaaaaa + {a for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb} | ||
|
||
|
||
# But only for expressions that have a statement parent. | ||
not (aaaaaaaaaaaaaa + {a for x in bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb}) | ||
[a + [bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb] in c ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
115 changes: 111 additions & 4 deletions
115
crates/ruff_python_formatter/src/expression/expr_bin_op.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,119 @@ | ||
use crate::{verbatim_text, FormatNodeRule, PyFormatter}; | ||
use ruff_formatter::{write, Buffer, FormatResult}; | ||
use rustpython_parser::ast::ExprBinOp; | ||
use crate::comments::trailing_comments; | ||
use crate::prelude::*; | ||
use crate::FormatNodeRule; | ||
use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule}; | ||
use ruff_python_ast::node::{AnyNodeRef, AstNode}; | ||
use rustpython_parser::ast::{ | ||
Constant, Expr, ExprAttribute, ExprBinOp, ExprConstant, ExprUnaryOp, Operator, Unaryop, | ||
}; | ||
|
||
#[derive(Default)] | ||
pub struct FormatExprBinOp; | ||
|
||
impl FormatNodeRule<ExprBinOp> for FormatExprBinOp { | ||
fn fmt_fields(&self, item: &ExprBinOp, f: &mut PyFormatter) -> FormatResult<()> { | ||
write!(f, [verbatim_text(item.range)]) | ||
let ExprBinOp { | ||
left, | ||
right, | ||
op, | ||
range: _, | ||
} = item; | ||
|
||
let needs_space = !is_simple_power_expression(item); | ||
|
||
let before_operator_space = if needs_space { | ||
soft_line_break_or_space() | ||
} else { | ||
soft_line_break() | ||
}; | ||
|
||
let comments = f.context().comments().clone(); | ||
let operator_comments = comments.dangling_comments(item.as_any_node_ref()); | ||
|
||
write!( | ||
f, | ||
[ | ||
left.format(), | ||
before_operator_space, | ||
op.format(), | ||
trailing_comments(operator_comments), | ||
] | ||
)?; | ||
|
||
// Format the operator on its own line if it has any trailing comments at the right side has leading comments. | ||
if !operator_comments.is_empty() && comments.has_leading_comments(right.as_ref().into()) { | ||
write!(f, [hard_line_break()])?; | ||
} else if needs_space { | ||
write!(f, [space()])?; | ||
} | ||
|
||
write!(f, [group(&right.format())]) | ||
} | ||
|
||
fn fmt_dangling_comments(&self, _node: &ExprBinOp, _f: &mut PyFormatter) -> FormatResult<()> { | ||
// Handled inside of `fmt_fields` | ||
Ok(()) | ||
} | ||
} | ||
|
||
const fn is_simple_power_expression(expr: &ExprBinOp) -> bool { | ||
expr.op.is_pow() && is_simple_power_operand(&expr.left) && is_simple_power_operand(&expr.right) | ||
} | ||
|
||
/// Return `true` if an [`Expr`] adheres to Black's definition of a non-complex | ||
/// expression, in the context of a power operation. | ||
const fn is_simple_power_operand(expr: &Expr) -> bool { | ||
match expr { | ||
Expr::UnaryOp(ExprUnaryOp { | ||
op: Unaryop::Not, .. | ||
}) => false, | ||
Expr::Constant(ExprConstant { | ||
value: Constant::Complex { .. } | Constant::Float(_) | Constant::Int(_), | ||
.. | ||
}) => true, | ||
Expr::Name(_) => true, | ||
Expr::UnaryOp(ExprUnaryOp { operand, .. }) => is_simple_power_operand(operand), | ||
Expr::Attribute(ExprAttribute { value, .. }) => is_simple_power_operand(value), | ||
_ => false, | ||
} | ||
} | ||
|
||
#[derive(Copy, Clone)] | ||
pub struct FormatOperator; | ||
|
||
impl<'ast> AsFormat<PyFormatContext<'ast>> for Operator { | ||
type Format<'a> = FormatRefWithRule<'a, Operator, FormatOperator, PyFormatContext<'ast>>; | ||
|
||
fn format(&self) -> Self::Format<'_> { | ||
FormatRefWithRule::new(self, FormatOperator) | ||
} | ||
} | ||
|
||
impl<'ast> IntoFormat<PyFormatContext<'ast>> for Operator { | ||
type Format = FormatOwnedWithRule<Operator, FormatOperator, PyFormatContext<'ast>>; | ||
fn into_format(self) -> Self::Format { | ||
FormatOwnedWithRule::new(self, FormatOperator) | ||
} | ||
} | ||
|
||
impl FormatRule<Operator, PyFormatContext<'_>> for FormatOperator { | ||
fn fmt(&self, item: &Operator, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> { | ||
let operator = match item { | ||
Operator::Add => "+", | ||
Operator::Sub => "-", | ||
Operator::Mult => "*", | ||
Operator::MatMult => "@", | ||
Operator::Div => "/", | ||
Operator::Mod => "%", | ||
Operator::Pow => "**", | ||
Operator::LShift => "<<", | ||
Operator::RShift => ">>", | ||
Operator::BitOr => "|", | ||
Operator::BitXor => "^", | ||
Operator::BitAnd => "&", | ||
Operator::FloorDiv => "//", | ||
}; | ||
|
||
text(operator).fmt(f) | ||
} | ||
} |
53 changes: 0 additions & 53 deletions
53
crates/ruff_python_formatter/src/expression/maybe_parenthesize.rs
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.