mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 12:55:05 +00:00

<!-- 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 I started working on this because I assumed that I would need access to options inside of `NeedsParantheses` but it then turned out that I won't. Anyway, it kind of felt nice to pass fewer arguments. So I'm gonna put this out here to get your feedback if you prefer this over passing individual fiels. Oh, I sneeked in another change. I renamed `context.contents` to `source`. `contents` is too generic and doesn't tell you anything. <!-- What's the purpose of the change? What does it do, and why? --> ## Test Plan It compiles
115 lines
3.3 KiB
Rust
115 lines
3.3 KiB
Rust
use crate::comments::leading_comments;
|
|
use crate::expression::parentheses::{
|
|
default_expression_needs_parentheses, in_parentheses_only_group, NeedsParentheses, Parentheses,
|
|
Parenthesize,
|
|
};
|
|
use crate::prelude::*;
|
|
use crate::FormatNodeRule;
|
|
use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule, FormatRuleWithOptions};
|
|
use rustpython_parser::ast::{CmpOp, ExprCompare};
|
|
|
|
#[derive(Default)]
|
|
pub struct FormatExprCompare {
|
|
parentheses: Option<Parentheses>,
|
|
}
|
|
|
|
impl FormatRuleWithOptions<ExprCompare, PyFormatContext<'_>> for FormatExprCompare {
|
|
type Options = Option<Parentheses>;
|
|
|
|
fn with_options(mut self, options: Self::Options) -> Self {
|
|
self.parentheses = options;
|
|
self
|
|
}
|
|
}
|
|
|
|
impl FormatNodeRule<ExprCompare> for FormatExprCompare {
|
|
fn fmt_fields(&self, item: &ExprCompare, f: &mut PyFormatter) -> FormatResult<()> {
|
|
let ExprCompare {
|
|
range: _,
|
|
left,
|
|
ops,
|
|
comparators,
|
|
} = item;
|
|
|
|
let comments = f.context().comments().clone();
|
|
|
|
write!(f, [in_parentheses_only_group(&left.format())])?;
|
|
|
|
assert_eq!(comparators.len(), ops.len());
|
|
|
|
for (operator, comparator) in ops.iter().zip(comparators) {
|
|
let leading_comparator_comments = comments.leading_comments(comparator);
|
|
if leading_comparator_comments.is_empty() {
|
|
write!(f, [soft_line_break_or_space()])?;
|
|
} else {
|
|
// Format the expressions leading comments **before** the operator
|
|
write!(
|
|
f,
|
|
[
|
|
hard_line_break(),
|
|
leading_comments(leading_comparator_comments)
|
|
]
|
|
)?;
|
|
}
|
|
|
|
write!(
|
|
f,
|
|
[
|
|
operator.format(),
|
|
space(),
|
|
in_parentheses_only_group(&comparator.format())
|
|
]
|
|
)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl NeedsParentheses for ExprCompare {
|
|
fn needs_parentheses(
|
|
&self,
|
|
parenthesize: Parenthesize,
|
|
context: &PyFormatContext,
|
|
) -> Parentheses {
|
|
default_expression_needs_parentheses(self.into(), parenthesize, context)
|
|
}
|
|
}
|
|
|
|
#[derive(Copy, Clone)]
|
|
pub struct FormatCmpOp;
|
|
|
|
impl<'ast> AsFormat<PyFormatContext<'ast>> for CmpOp {
|
|
type Format<'a> = FormatRefWithRule<'a, CmpOp, FormatCmpOp, PyFormatContext<'ast>>;
|
|
|
|
fn format(&self) -> Self::Format<'_> {
|
|
FormatRefWithRule::new(self, FormatCmpOp)
|
|
}
|
|
}
|
|
|
|
impl<'ast> IntoFormat<PyFormatContext<'ast>> for CmpOp {
|
|
type Format = FormatOwnedWithRule<CmpOp, FormatCmpOp, PyFormatContext<'ast>>;
|
|
|
|
fn into_format(self) -> Self::Format {
|
|
FormatOwnedWithRule::new(self, FormatCmpOp)
|
|
}
|
|
}
|
|
|
|
impl FormatRule<CmpOp, PyFormatContext<'_>> for FormatCmpOp {
|
|
fn fmt(&self, item: &CmpOp, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
|
let operator = match item {
|
|
CmpOp::Eq => "==",
|
|
CmpOp::NotEq => "!=",
|
|
CmpOp::Lt => "<",
|
|
CmpOp::LtE => "<=",
|
|
CmpOp::Gt => ">",
|
|
CmpOp::GtE => ">=",
|
|
CmpOp::Is => "is",
|
|
CmpOp::IsNot => "is not",
|
|
CmpOp::In => "in",
|
|
CmpOp::NotIn => "not in",
|
|
};
|
|
|
|
text(operator).fmt(f)
|
|
}
|
|
}
|