diff --git a/crates/ruff_formatter/src/builders.rs b/crates/ruff_formatter/src/builders.rs index 885e9f9ec5a41..35d8a9362860b 100644 --- a/crates/ruff_formatter/src/builders.rs +++ b/crates/ruff_formatter/src/builders.rs @@ -2362,7 +2362,6 @@ impl<'a, 'buf, Context> FillBuilder<'a, 'buf, Context> { #[derive(Copy, Clone)] pub struct BestFitting<'a, Context> { variants: Arguments<'a, Context>, - mode: BestFittingMode, } impl<'a, Context> BestFitting<'a, Context> { @@ -2380,115 +2379,7 @@ impl<'a, Context> BestFitting<'a, Context> { "Requires at least the least expanded and most expanded variants" ); - Self { - variants, - mode: BestFittingMode::default(), - } - } - - /// Changes the mode used by this best fitting element to determine whether a variant fits. - /// - /// ## Examples - /// - /// ### All Lines - /// - /// ``` - /// use ruff_formatter::{Formatted, LineWidth, format, format_args, SimpleFormatOptions}; - /// use ruff_formatter::prelude::*; - /// - /// # fn main() -> FormatResult<()> { - /// let formatted = format!( - /// SimpleFormatContext::default(), - /// [ - /// best_fitting!( - /// // Everything fits on a single line - /// format_args!( - /// group(&format_args![ - /// text("["), - /// soft_block_indent(&format_args![ - /// text("1,"), - /// soft_line_break_or_space(), - /// text("2,"), - /// soft_line_break_or_space(), - /// text("3"), - /// ]), - /// text("]") - /// ]), - /// space(), - /// text("+"), - /// space(), - /// text("aVeryLongIdentifier") - /// ), - /// - /// // Breaks after `[` and prints each elements on a single line - /// // The group is necessary because the variant, by default is printed in flat mode and a - /// // hard line break indicates that the content doesn't fit. - /// format_args!( - /// text("["), - /// group(&block_indent(&format_args![text("1,"), hard_line_break(), text("2,"), hard_line_break(), text("3")])).should_expand(true), - /// text("]"), - /// space(), - /// text("+"), - /// space(), - /// text("aVeryLongIdentifier") - /// ), - /// - /// // Adds parentheses and indents the body, breaks after the operator - /// format_args!( - /// text("("), - /// block_indent(&format_args![ - /// text("["), - /// block_indent(&format_args![ - /// text("1,"), - /// hard_line_break(), - /// text("2,"), - /// hard_line_break(), - /// text("3"), - /// ]), - /// text("]"), - /// hard_line_break(), - /// text("+"), - /// space(), - /// text("aVeryLongIdentifier") - /// ]), - /// text(")") - /// ) - /// ).with_mode(BestFittingMode::AllLines) - /// ] - /// )?; - /// - /// let document = formatted.into_document(); - /// - /// // Takes the first variant if everything fits on a single line - /// assert_eq!( - /// "[1, 2, 3] + aVeryLongIdentifier", - /// Formatted::new(document.clone(), SimpleFormatContext::default()) - /// .print()? - /// .as_code() - /// ); - /// - /// // It takes the second if the first variant doesn't fit on a single line. The second variant - /// // has some additional line breaks to make sure inner groups don't break - /// assert_eq!( - /// "[\n\t1,\n\t2,\n\t3\n] + aVeryLongIdentifier", - /// Formatted::new(document.clone(), SimpleFormatContext::new(SimpleFormatOptions { line_width: 23.try_into().unwrap(), ..SimpleFormatOptions::default() })) - /// .print()? - /// .as_code() - /// ); - /// - /// // Prints the last option as last resort - /// assert_eq!( - /// "(\n\t[\n\t\t1,\n\t\t2,\n\t\t3\n\t]\n\t+ aVeryLongIdentifier\n)", - /// Formatted::new(document.clone(), SimpleFormatContext::new(SimpleFormatOptions { line_width: 22.try_into().unwrap(), ..SimpleFormatOptions::default() })) - /// .print()? - /// .as_code() - /// ); - /// # Ok(()) - /// # } - /// ``` - pub fn with_mode(mut self, mode: BestFittingMode) -> Self { - self.mode = mode; - self + Self { variants } } } @@ -2514,7 +2405,6 @@ impl Format for BestFitting<'_, Context> { variants: format_element::BestFittingVariants::from_vec_unchecked( formatted_variants, ), - mode: self.mode, } }; diff --git a/crates/ruff_formatter/src/format_element.rs b/crates/ruff_formatter/src/format_element.rs index 5c5b3ff3e91a0..7506c9cb75371 100644 --- a/crates/ruff_formatter/src/format_element.rs +++ b/crates/ruff_formatter/src/format_element.rs @@ -57,10 +57,7 @@ pub enum FormatElement { /// A list of different variants representing the same content. The printer picks the best fitting content. /// Line breaks inside of a best fitting don't propagate to parent groups. - BestFitting { - variants: BestFittingVariants, - mode: BestFittingMode, - }, + BestFitting { variants: BestFittingVariants }, /// A [Tag] that marks the start/end of some content to which some special formatting is applied. Tag(Tag), @@ -87,10 +84,9 @@ impl std::fmt::Debug for FormatElement { .field(contains_newlines) .finish(), FormatElement::LineSuffixBoundary => write!(fmt, "LineSuffixBoundary"), - FormatElement::BestFitting { variants, mode } => fmt + FormatElement::BestFitting { variants } => fmt .debug_struct("BestFitting") .field("variants", variants) - .field("mode", &mode) .finish(), FormatElement::Interned(interned) => { fmt.debug_list().entries(interned.deref()).finish() @@ -301,29 +297,6 @@ impl FormatElements for FormatElement { } } -/// Mode used to determine if any variant (except the most expanded) fits for [`BestFittingVariants`]. -#[repr(u8)] -#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] -pub enum BestFittingMode { - /// The variant fits if the content up to the first hard or a soft line break inside a [`Group`] with - /// [`PrintMode::Expanded`] fits on the line. The default mode. - /// - /// [`Group`]: tag::Group - #[default] - FirstLine, - - /// A variant fits if all lines fit into the configured print width. A line ends if by any - /// hard or a soft line break inside a [`Group`] with [`PrintMode::Expanded`]. - /// The content doesn't fit if there's any hard line break outside a [`Group`] with [`PrintMode::Expanded`] - /// (a hard line break in content that should be considered in [`PrintMode::Flat`]. - /// - /// Use this mode with caution as it requires measuring all content of the variant which is more - /// expensive than using [`BestFittingMode::FirstLine`]. - /// - /// [`Group`]: tag::Group - AllLines, -} - /// The different variants for this element. /// The first element is the one that takes up the most space horizontally (the most flat), /// The last element takes up the least space horizontally (but most horizontal space). diff --git a/crates/ruff_formatter/src/format_element/document.rs b/crates/ruff_formatter/src/format_element/document.rs index 1f031f0e1d39f..7eb1c37156ef8 100644 --- a/crates/ruff_formatter/src/format_element/document.rs +++ b/crates/ruff_formatter/src/format_element/document.rs @@ -80,7 +80,7 @@ impl Document { interned_expands } }, - FormatElement::BestFitting { variants, mode: _ } => { + FormatElement::BestFitting { variants } => { enclosing.push(Enclosing::BestFitting); for variant in variants { @@ -303,7 +303,7 @@ impl Format> for &[FormatElement] { write!(f, [text("line_suffix_boundary")])?; } - FormatElement::BestFitting { variants, mode } => { + FormatElement::BestFitting { variants } => { write!(f, [text("best_fitting([")])?; f.write_elements([ FormatElement::Tag(StartIndent), @@ -319,16 +319,6 @@ impl Format> for &[FormatElement] { FormatElement::Line(LineMode::Hard), ])?; - if *mode != BestFittingMode::FirstLine { - write!( - f, - [ - dynamic_text(&std::format!("mode: {mode:?},"), None), - space() - ] - )?; - } - write!(f, [text("])")])?; } diff --git a/crates/ruff_formatter/src/printer/mod.rs b/crates/ruff_formatter/src/printer/mod.rs index a58514c10271d..2bcb7fe582e29 100644 --- a/crates/ruff_formatter/src/printer/mod.rs +++ b/crates/ruff_formatter/src/printer/mod.rs @@ -6,7 +6,7 @@ mod stack; use crate::format_element::document::Document; use crate::format_element::tag::{Condition, GroupMode}; -use crate::format_element::{BestFittingMode, BestFittingVariants, LineMode, PrintMode}; +use crate::format_element::{BestFittingVariants, LineMode, PrintMode}; use crate::prelude::tag; use crate::prelude::tag::{DedentMode, Tag, TagKind, VerbatimKind}; use crate::printer::call_stack::{ @@ -135,8 +135,8 @@ impl<'a> Printer<'a> { self.flush_line_suffixes(queue, stack, Some(HARD_BREAK)); } - FormatElement::BestFitting { variants, mode } => { - self.print_best_fitting(variants, *mode, queue, stack)?; + FormatElement::BestFitting { variants } => { + self.print_best_fitting(variants, queue, stack)?; } FormatElement::Interned(content) => { @@ -426,7 +426,6 @@ impl<'a> Printer<'a> { fn print_best_fitting( &mut self, variants: &'a BestFittingVariants, - mode: BestFittingMode, queue: &mut PrintQueue<'a>, stack: &mut PrintCallStack, ) -> PrintResult<()> { @@ -452,9 +451,7 @@ impl<'a> Printer<'a> { // args must be popped from the stack as soon as it sees the matching end entry. let content = &variant[1..]; - let entry_args = args - .with_print_mode(PrintMode::Flat) - .with_measure_mode(MeasureMode::from(mode)); + let entry_args = args.with_print_mode(PrintMode::Flat); queue.extend_back(content); stack.push(TagKind::Entry, entry_args); @@ -1065,13 +1062,10 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { FormatElement::SourcePosition(_) => {} - FormatElement::BestFitting { variants, mode } => { - let (slice, args) = match args.mode() { - PrintMode::Flat => ( - variants.most_flat(), - args.with_measure_mode(MeasureMode::from(*mode)), - ), - PrintMode::Expanded => (variants.most_expanded(), args), + FormatElement::BestFitting { variants } => { + let slice = match args.mode() { + PrintMode::Flat => variants.most_flat(), + PrintMode::Expanded => variants.most_expanded(), }; if !matches!(slice.first(), Some(FormatElement::Tag(Tag::StartEntry))) { @@ -1385,15 +1379,6 @@ enum MeasureMode { AllLines, } -impl From for MeasureMode { - fn from(value: BestFittingMode) -> Self { - match value { - BestFittingMode::FirstLine => Self::FirstLine, - BestFittingMode::AllLines => Self::AllLines, - } - } -} - #[cfg(test)] mod tests { use crate::prelude::*; diff --git a/crates/ruff_python_ast/src/expression.rs b/crates/ruff_python_ast/src/expression.rs new file mode 100644 index 0000000000000..1f3d72f46831d --- /dev/null +++ b/crates/ruff_python_ast/src/expression.rs @@ -0,0 +1,564 @@ +use crate::node::AnyNodeRef; +use crate::visitor::preorder::PreorderVisitor; +use ruff_text_size::TextRange; +use rustpython_ast::{Expr, Ranged}; +use rustpython_parser::ast; + +/// Unowned pendant to [`ast::Expr`] that stores a reference instead of a owned value. +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ExpressionRef<'a> { + BoolOp(&'a ast::ExprBoolOp), + NamedExpr(&'a ast::ExprNamedExpr), + BinOp(&'a ast::ExprBinOp), + UnaryOp(&'a ast::ExprUnaryOp), + Lambda(&'a ast::ExprLambda), + IfExp(&'a ast::ExprIfExp), + Dict(&'a ast::ExprDict), + Set(&'a ast::ExprSet), + ListComp(&'a ast::ExprListComp), + SetComp(&'a ast::ExprSetComp), + DictComp(&'a ast::ExprDictComp), + GeneratorExp(&'a ast::ExprGeneratorExp), + Await(&'a ast::ExprAwait), + Yield(&'a ast::ExprYield), + YieldFrom(&'a ast::ExprYieldFrom), + Compare(&'a ast::ExprCompare), + Call(&'a ast::ExprCall), + FormattedValue(&'a ast::ExprFormattedValue), + JoinedStr(&'a ast::ExprJoinedStr), + Constant(&'a ast::ExprConstant), + Attribute(&'a ast::ExprAttribute), + Subscript(&'a ast::ExprSubscript), + Starred(&'a ast::ExprStarred), + Name(&'a ast::ExprName), + List(&'a ast::ExprList), + Tuple(&'a ast::ExprTuple), + Slice(&'a ast::ExprSlice), +} + +impl<'a> From<&'a Box> for ExpressionRef<'a> { + fn from(value: &'a Box) -> Self { + ExpressionRef::from(value.as_ref()) + } +} + +impl<'a> From<&'a Expr> for ExpressionRef<'a> { + fn from(value: &'a Expr) -> Self { + match value { + Expr::BoolOp(value) => ExpressionRef::BoolOp(value), + Expr::NamedExpr(value) => ExpressionRef::NamedExpr(value), + Expr::BinOp(value) => ExpressionRef::BinOp(value), + Expr::UnaryOp(value) => ExpressionRef::UnaryOp(value), + Expr::Lambda(value) => ExpressionRef::Lambda(value), + Expr::IfExp(value) => ExpressionRef::IfExp(value), + Expr::Dict(value) => ExpressionRef::Dict(value), + Expr::Set(value) => ExpressionRef::Set(value), + Expr::ListComp(value) => ExpressionRef::ListComp(value), + Expr::SetComp(value) => ExpressionRef::SetComp(value), + Expr::DictComp(value) => ExpressionRef::DictComp(value), + Expr::GeneratorExp(value) => ExpressionRef::GeneratorExp(value), + Expr::Await(value) => ExpressionRef::Await(value), + Expr::Yield(value) => ExpressionRef::Yield(value), + Expr::YieldFrom(value) => ExpressionRef::YieldFrom(value), + Expr::Compare(value) => ExpressionRef::Compare(value), + Expr::Call(value) => ExpressionRef::Call(value), + Expr::FormattedValue(value) => ExpressionRef::FormattedValue(value), + Expr::JoinedStr(value) => ExpressionRef::JoinedStr(value), + Expr::Constant(value) => ExpressionRef::Constant(value), + Expr::Attribute(value) => ExpressionRef::Attribute(value), + Expr::Subscript(value) => ExpressionRef::Subscript(value), + Expr::Starred(value) => ExpressionRef::Starred(value), + Expr::Name(value) => ExpressionRef::Name(value), + Expr::List(value) => ExpressionRef::List(value), + Expr::Tuple(value) => ExpressionRef::Tuple(value), + Expr::Slice(value) => ExpressionRef::Slice(value), + } + } +} + +impl<'a> From<&'a ast::ExprBoolOp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprBoolOp) -> Self { + Self::BoolOp(value) + } +} +impl<'a> From<&'a ast::ExprNamedExpr> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprNamedExpr) -> Self { + Self::NamedExpr(value) + } +} +impl<'a> From<&'a ast::ExprBinOp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprBinOp) -> Self { + Self::BinOp(value) + } +} +impl<'a> From<&'a ast::ExprUnaryOp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprUnaryOp) -> Self { + Self::UnaryOp(value) + } +} +impl<'a> From<&'a ast::ExprLambda> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprLambda) -> Self { + Self::Lambda(value) + } +} +impl<'a> From<&'a ast::ExprIfExp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprIfExp) -> Self { + Self::IfExp(value) + } +} +impl<'a> From<&'a ast::ExprDict> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprDict) -> Self { + Self::Dict(value) + } +} +impl<'a> From<&'a ast::ExprSet> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprSet) -> Self { + Self::Set(value) + } +} +impl<'a> From<&'a ast::ExprListComp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprListComp) -> Self { + Self::ListComp(value) + } +} +impl<'a> From<&'a ast::ExprSetComp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprSetComp) -> Self { + Self::SetComp(value) + } +} +impl<'a> From<&'a ast::ExprDictComp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprDictComp) -> Self { + Self::DictComp(value) + } +} +impl<'a> From<&'a ast::ExprGeneratorExp> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprGeneratorExp) -> Self { + Self::GeneratorExp(value) + } +} +impl<'a> From<&'a ast::ExprAwait> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprAwait) -> Self { + Self::Await(value) + } +} +impl<'a> From<&'a ast::ExprYield> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprYield) -> Self { + Self::Yield(value) + } +} +impl<'a> From<&'a ast::ExprYieldFrom> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprYieldFrom) -> Self { + Self::YieldFrom(value) + } +} +impl<'a> From<&'a ast::ExprCompare> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprCompare) -> Self { + Self::Compare(value) + } +} +impl<'a> From<&'a ast::ExprCall> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprCall) -> Self { + Self::Call(value) + } +} +impl<'a> From<&'a ast::ExprFormattedValue> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprFormattedValue) -> Self { + Self::FormattedValue(value) + } +} +impl<'a> From<&'a ast::ExprJoinedStr> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprJoinedStr) -> Self { + Self::JoinedStr(value) + } +} +impl<'a> From<&'a ast::ExprConstant> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprConstant) -> Self { + Self::Constant(value) + } +} +impl<'a> From<&'a ast::ExprAttribute> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprAttribute) -> Self { + Self::Attribute(value) + } +} +impl<'a> From<&'a ast::ExprSubscript> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprSubscript) -> Self { + Self::Subscript(value) + } +} +impl<'a> From<&'a ast::ExprStarred> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprStarred) -> Self { + Self::Starred(value) + } +} +impl<'a> From<&'a ast::ExprName> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprName) -> Self { + Self::Name(value) + } +} +impl<'a> From<&'a ast::ExprList> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprList) -> Self { + Self::List(value) + } +} +impl<'a> From<&'a ast::ExprTuple> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprTuple) -> Self { + Self::Tuple(value) + } +} +impl<'a> From<&'a ast::ExprSlice> for ExpressionRef<'a> { + fn from(value: &'a ast::ExprSlice) -> Self { + Self::Slice(value) + } +} + +impl<'a> From> for AnyNodeRef<'a> { + fn from(value: ExpressionRef<'a>) -> Self { + match value { + ExpressionRef::BoolOp(expression) => AnyNodeRef::ExprBoolOp(expression), + ExpressionRef::NamedExpr(expression) => AnyNodeRef::ExprNamedExpr(expression), + ExpressionRef::BinOp(expression) => AnyNodeRef::ExprBinOp(expression), + ExpressionRef::UnaryOp(expression) => AnyNodeRef::ExprUnaryOp(expression), + ExpressionRef::Lambda(expression) => AnyNodeRef::ExprLambda(expression), + ExpressionRef::IfExp(expression) => AnyNodeRef::ExprIfExp(expression), + ExpressionRef::Dict(expression) => AnyNodeRef::ExprDict(expression), + ExpressionRef::Set(expression) => AnyNodeRef::ExprSet(expression), + ExpressionRef::ListComp(expression) => AnyNodeRef::ExprListComp(expression), + ExpressionRef::SetComp(expression) => AnyNodeRef::ExprSetComp(expression), + ExpressionRef::DictComp(expression) => AnyNodeRef::ExprDictComp(expression), + ExpressionRef::GeneratorExp(expression) => AnyNodeRef::ExprGeneratorExp(expression), + ExpressionRef::Await(expression) => AnyNodeRef::ExprAwait(expression), + ExpressionRef::Yield(expression) => AnyNodeRef::ExprYield(expression), + ExpressionRef::YieldFrom(expression) => AnyNodeRef::ExprYieldFrom(expression), + ExpressionRef::Compare(expression) => AnyNodeRef::ExprCompare(expression), + ExpressionRef::Call(expression) => AnyNodeRef::ExprCall(expression), + ExpressionRef::FormattedValue(expression) => AnyNodeRef::ExprFormattedValue(expression), + ExpressionRef::JoinedStr(expression) => AnyNodeRef::ExprJoinedStr(expression), + ExpressionRef::Constant(expression) => AnyNodeRef::ExprConstant(expression), + ExpressionRef::Attribute(expression) => AnyNodeRef::ExprAttribute(expression), + ExpressionRef::Subscript(expression) => AnyNodeRef::ExprSubscript(expression), + ExpressionRef::Starred(expression) => AnyNodeRef::ExprStarred(expression), + ExpressionRef::Name(expression) => AnyNodeRef::ExprName(expression), + ExpressionRef::List(expression) => AnyNodeRef::ExprList(expression), + ExpressionRef::Tuple(expression) => AnyNodeRef::ExprTuple(expression), + ExpressionRef::Slice(expression) => AnyNodeRef::ExprSlice(expression), + } + } +} + +impl Ranged for ExpressionRef<'_> { + fn range(&self) -> TextRange { + match self { + ExpressionRef::BoolOp(expression) => expression.range(), + ExpressionRef::NamedExpr(expression) => expression.range(), + ExpressionRef::BinOp(expression) => expression.range(), + ExpressionRef::UnaryOp(expression) => expression.range(), + ExpressionRef::Lambda(expression) => expression.range(), + ExpressionRef::IfExp(expression) => expression.range(), + ExpressionRef::Dict(expression) => expression.range(), + ExpressionRef::Set(expression) => expression.range(), + ExpressionRef::ListComp(expression) => expression.range(), + ExpressionRef::SetComp(expression) => expression.range(), + ExpressionRef::DictComp(expression) => expression.range(), + ExpressionRef::GeneratorExp(expression) => expression.range(), + ExpressionRef::Await(expression) => expression.range(), + ExpressionRef::Yield(expression) => expression.range(), + ExpressionRef::YieldFrom(expression) => expression.range(), + ExpressionRef::Compare(expression) => expression.range(), + ExpressionRef::Call(expression) => expression.range(), + ExpressionRef::FormattedValue(expression) => expression.range(), + ExpressionRef::JoinedStr(expression) => expression.range(), + ExpressionRef::Constant(expression) => expression.range(), + ExpressionRef::Attribute(expression) => expression.range(), + ExpressionRef::Subscript(expression) => expression.range(), + ExpressionRef::Starred(expression) => expression.range(), + ExpressionRef::Name(expression) => expression.range(), + ExpressionRef::List(expression) => expression.range(), + ExpressionRef::Tuple(expression) => expression.range(), + ExpressionRef::Slice(expression) => expression.range(), + } + } +} + +pub fn walk_expression_ref<'a, V>(visitor: &mut V, expr: ExpressionRef<'a>) +where + V: PreorderVisitor<'a> + ?Sized, +{ + match expr { + ExpressionRef::BoolOp(ast::ExprBoolOp { + op, + values, + range: _range, + }) => match values.as_slice() { + [left, rest @ ..] => { + visitor.visit_expr(left); + visitor.visit_bool_op(op); + for expr in rest { + visitor.visit_expr(expr); + } + } + [] => { + visitor.visit_bool_op(op); + } + }, + + ExpressionRef::NamedExpr(ast::ExprNamedExpr { + target, + value, + range: _range, + }) => { + visitor.visit_expr(target); + visitor.visit_expr(value); + } + + ExpressionRef::BinOp(ast::ExprBinOp { + left, + op, + right, + range: _range, + }) => { + visitor.visit_expr(left); + visitor.visit_operator(op); + visitor.visit_expr(right); + } + + ExpressionRef::UnaryOp(ast::ExprUnaryOp { + op, + operand, + range: _range, + }) => { + visitor.visit_unary_op(op); + visitor.visit_expr(operand); + } + + ExpressionRef::Lambda(ast::ExprLambda { + args, + body, + range: _range, + }) => { + visitor.visit_arguments(args); + visitor.visit_expr(body); + } + + ExpressionRef::IfExp(ast::ExprIfExp { + test, + body, + orelse, + range: _range, + }) => { + // `body if test else orelse` + visitor.visit_expr(body); + visitor.visit_expr(test); + visitor.visit_expr(orelse); + } + + ExpressionRef::Dict(ast::ExprDict { + keys, + values, + range: _range, + }) => { + for (key, value) in keys.iter().zip(values) { + if let Some(key) = key { + visitor.visit_expr(key); + } + visitor.visit_expr(value); + } + } + + ExpressionRef::Set(ast::ExprSet { + elts, + range: _range, + }) => { + for expr in elts { + visitor.visit_expr(expr); + } + } + + ExpressionRef::ListComp(ast::ExprListComp { + elt, + generators, + range: _range, + }) => { + visitor.visit_expr(elt); + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } + + ExpressionRef::SetComp(ast::ExprSetComp { + elt, + generators, + range: _range, + }) => { + visitor.visit_expr(elt); + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } + + ExpressionRef::DictComp(ast::ExprDictComp { + key, + value, + generators, + range: _range, + }) => { + visitor.visit_expr(key); + visitor.visit_expr(value); + + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } + + ExpressionRef::GeneratorExp(ast::ExprGeneratorExp { + elt, + generators, + range: _range, + }) => { + visitor.visit_expr(elt); + for comprehension in generators { + visitor.visit_comprehension(comprehension); + } + } + + ExpressionRef::Await(ast::ExprAwait { + value, + range: _range, + }) + | ExpressionRef::YieldFrom(ast::ExprYieldFrom { + value, + range: _range, + }) => visitor.visit_expr(value), + + ExpressionRef::Yield(ast::ExprYield { + value, + range: _range, + }) => { + if let Some(expr) = value { + visitor.visit_expr(expr); + } + } + + ExpressionRef::Compare(ast::ExprCompare { + left, + ops, + comparators, + range: _range, + }) => { + visitor.visit_expr(left); + + for (op, comparator) in ops.iter().zip(comparators) { + visitor.visit_cmp_op(op); + visitor.visit_expr(comparator); + } + } + + ExpressionRef::Call(ast::ExprCall { + func, + args, + keywords, + range: _range, + }) => { + visitor.visit_expr(func); + for expr in args { + visitor.visit_expr(expr); + } + for keyword in keywords { + visitor.visit_keyword(keyword); + } + } + + ExpressionRef::FormattedValue(ast::ExprFormattedValue { + value, format_spec, .. + }) => { + visitor.visit_expr(value); + + if let Some(expr) = format_spec { + visitor.visit_format_spec(expr); + } + } + + ExpressionRef::JoinedStr(ast::ExprJoinedStr { + values, + range: _range, + }) => { + for expr in values { + visitor.visit_expr(expr); + } + } + + ExpressionRef::Constant(ast::ExprConstant { + value, + range: _, + kind: _, + }) => visitor.visit_constant(value), + + ExpressionRef::Attribute(ast::ExprAttribute { + value, + attr: _, + ctx: _, + range: _, + }) => { + visitor.visit_expr(value); + } + + ExpressionRef::Subscript(ast::ExprSubscript { + value, + slice, + ctx: _, + range: _range, + }) => { + visitor.visit_expr(value); + visitor.visit_expr(slice); + } + ExpressionRef::Starred(ast::ExprStarred { + value, + ctx: _, + range: _range, + }) => { + visitor.visit_expr(value); + } + + ExpressionRef::Name(ast::ExprName { + id: _, + ctx: _, + range: _, + }) => {} + + ExpressionRef::List(ast::ExprList { + elts, + ctx: _, + range: _range, + }) => { + for expr in elts { + visitor.visit_expr(expr); + } + } + ExpressionRef::Tuple(ast::ExprTuple { + elts, + ctx: _, + range: _range, + }) => { + for expr in elts { + visitor.visit_expr(expr); + } + } + + ExpressionRef::Slice(ast::ExprSlice { + lower, + upper, + step, + range: _range, + }) => { + if let Some(expr) = lower { + visitor.visit_expr(expr); + } + if let Some(expr) = upper { + visitor.visit_expr(expr); + } + if let Some(expr) = step { + visitor.visit_expr(expr); + } + } + } +} diff --git a/crates/ruff_python_ast/src/lib.rs b/crates/ruff_python_ast/src/lib.rs index 72928ec9e96dd..b8b7d883f4975 100644 --- a/crates/ruff_python_ast/src/lib.rs +++ b/crates/ruff_python_ast/src/lib.rs @@ -3,6 +3,7 @@ pub mod call_path; pub mod cast; pub mod comparable; pub mod docstrings; +pub mod expression; pub mod function; pub mod hashable; pub mod helpers; diff --git a/crates/ruff_python_ast/src/visitor/preorder.rs b/crates/ruff_python_ast/src/visitor/preorder.rs index 4a21e82bade15..638290bc218a2 100644 --- a/crates/ruff_python_ast/src/visitor/preorder.rs +++ b/crates/ruff_python_ast/src/visitor/preorder.rs @@ -1,3 +1,4 @@ +use crate::expression::{walk_expression_ref, ExpressionRef}; use rustpython_ast::{ArgWithDefault, Mod, TypeIgnore}; use rustpython_parser::ast::{ self, Alias, Arg, Arguments, BoolOp, CmpOp, Comprehension, Constant, Decorator, ExceptHandler, @@ -414,283 +415,7 @@ pub fn walk_expr<'a, V>(visitor: &mut V, expr: &'a Expr) where V: PreorderVisitor<'a> + ?Sized, { - match expr { - Expr::BoolOp(ast::ExprBoolOp { - op, - values, - range: _range, - }) => match values.as_slice() { - [left, rest @ ..] => { - visitor.visit_expr(left); - visitor.visit_bool_op(op); - for expr in rest { - visitor.visit_expr(expr); - } - } - [] => { - visitor.visit_bool_op(op); - } - }, - - Expr::NamedExpr(ast::ExprNamedExpr { - target, - value, - range: _range, - }) => { - visitor.visit_expr(target); - visitor.visit_expr(value); - } - - Expr::BinOp(ast::ExprBinOp { - left, - op, - right, - range: _range, - }) => { - visitor.visit_expr(left); - visitor.visit_operator(op); - visitor.visit_expr(right); - } - - Expr::UnaryOp(ast::ExprUnaryOp { - op, - operand, - range: _range, - }) => { - visitor.visit_unary_op(op); - visitor.visit_expr(operand); - } - - Expr::Lambda(ast::ExprLambda { - args, - body, - range: _range, - }) => { - visitor.visit_arguments(args); - visitor.visit_expr(body); - } - - Expr::IfExp(ast::ExprIfExp { - test, - body, - orelse, - range: _range, - }) => { - // `body if test else orelse` - visitor.visit_expr(body); - visitor.visit_expr(test); - visitor.visit_expr(orelse); - } - - Expr::Dict(ast::ExprDict { - keys, - values, - range: _range, - }) => { - for (key, value) in keys.iter().zip(values) { - if let Some(key) = key { - visitor.visit_expr(key); - } - visitor.visit_expr(value); - } - } - - Expr::Set(ast::ExprSet { - elts, - range: _range, - }) => { - for expr in elts { - visitor.visit_expr(expr); - } - } - - Expr::ListComp(ast::ExprListComp { - elt, - generators, - range: _range, - }) => { - visitor.visit_expr(elt); - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::SetComp(ast::ExprSetComp { - elt, - generators, - range: _range, - }) => { - visitor.visit_expr(elt); - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::DictComp(ast::ExprDictComp { - key, - value, - generators, - range: _range, - }) => { - visitor.visit_expr(key); - visitor.visit_expr(value); - - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::GeneratorExp(ast::ExprGeneratorExp { - elt, - generators, - range: _range, - }) => { - visitor.visit_expr(elt); - for comprehension in generators { - visitor.visit_comprehension(comprehension); - } - } - - Expr::Await(ast::ExprAwait { - value, - range: _range, - }) - | Expr::YieldFrom(ast::ExprYieldFrom { - value, - range: _range, - }) => visitor.visit_expr(value), - - Expr::Yield(ast::ExprYield { - value, - range: _range, - }) => { - if let Some(expr) = value { - visitor.visit_expr(expr); - } - } - - Expr::Compare(ast::ExprCompare { - left, - ops, - comparators, - range: _range, - }) => { - visitor.visit_expr(left); - - for (op, comparator) in ops.iter().zip(comparators) { - visitor.visit_cmp_op(op); - visitor.visit_expr(comparator); - } - } - - Expr::Call(ast::ExprCall { - func, - args, - keywords, - range: _range, - }) => { - visitor.visit_expr(func); - for expr in args { - visitor.visit_expr(expr); - } - for keyword in keywords { - visitor.visit_keyword(keyword); - } - } - - Expr::FormattedValue(ast::ExprFormattedValue { - value, format_spec, .. - }) => { - visitor.visit_expr(value); - - if let Some(expr) = format_spec { - visitor.visit_format_spec(expr); - } - } - - Expr::JoinedStr(ast::ExprJoinedStr { - values, - range: _range, - }) => { - for expr in values { - visitor.visit_expr(expr); - } - } - - Expr::Constant(ast::ExprConstant { - value, - range: _, - kind: _, - }) => visitor.visit_constant(value), - - Expr::Attribute(ast::ExprAttribute { - value, - attr: _, - ctx: _, - range: _, - }) => { - visitor.visit_expr(value); - } - - Expr::Subscript(ast::ExprSubscript { - value, - slice, - ctx: _, - range: _range, - }) => { - visitor.visit_expr(value); - visitor.visit_expr(slice); - } - Expr::Starred(ast::ExprStarred { - value, - ctx: _, - range: _range, - }) => { - visitor.visit_expr(value); - } - - Expr::Name(ast::ExprName { - id: _, - ctx: _, - range: _, - }) => {} - - Expr::List(ast::ExprList { - elts, - ctx: _, - range: _range, - }) => { - for expr in elts { - visitor.visit_expr(expr); - } - } - Expr::Tuple(ast::ExprTuple { - elts, - ctx: _, - range: _range, - }) => { - for expr in elts { - visitor.visit_expr(expr); - } - } - - Expr::Slice(ast::ExprSlice { - lower, - upper, - step, - range: _range, - }) => { - if let Some(expr) = lower { - visitor.visit_expr(expr); - } - if let Some(expr) = upper { - visitor.visit_expr(expr); - } - if let Some(expr) = step { - visitor.visit_expr(expr); - } - } - } + walk_expression_ref(visitor, ExpressionRef::from(expr)) } pub fn walk_constant<'a, V>(visitor: &mut V, constant: &'a Constant) diff --git a/crates/ruff_python_formatter/src/builders.rs b/crates/ruff_python_formatter/src/builders.rs index d39ff8a46dbde..8eeb07a819954 100644 --- a/crates/ruff_python_formatter/src/builders.rs +++ b/crates/ruff_python_formatter/src/builders.rs @@ -94,7 +94,7 @@ impl<'fmt, 'ast, 'buf> JoinNodesBuilder<'fmt, 'ast, 'buf> { self.result = self.result.and_then(|_| { if let Some(last_end) = self.last_end.replace(node.end()) { - let source = self.fmt.context().contents(); + let source = self.fmt.context().source(); let count_lines = |offset| { // It's necessary to skip any trailing line comment because RustPython doesn't include trailing comments // in the node's range @@ -262,7 +262,7 @@ impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> { if let Some(last_end) = self.end_of_last_entry.take() { let magic_trailing_comma = self.fmt.options().magic_trailing_comma().is_respect() && matches!( - first_non_trivia_token(last_end, self.fmt.context().contents()), + first_non_trivia_token(last_end, self.fmt.context().source()), Some(Token { kind: TokenKind::Comma, .. diff --git a/crates/ruff_python_formatter/src/comments/format.rs b/crates/ruff_python_formatter/src/comments/format.rs index c0a0a2a5bd3fc..84b0e3b654a6d 100644 --- a/crates/ruff_python_formatter/src/comments/format.rs +++ b/crates/ruff_python_formatter/src/comments/format.rs @@ -43,7 +43,7 @@ impl Format> for FormatLeadingComments<'_> { { let slice = comment.slice(); - let lines_after_comment = lines_after(slice.end(), f.context().contents()); + let lines_after_comment = lines_after(slice.end(), f.context().source()); write!( f, [format_comment(comment), empty_lines(lines_after_comment)] @@ -84,16 +84,16 @@ impl Format> for FormatLeadingAlternateBranchComments<'_> { if let Some(first_leading) = self.comments.first() { // Leading comments only preserves the lines after the comment but not before. // Insert the necessary lines. - if lines_before(first_leading.slice().start(), f.context().contents()) > 1 { + if lines_before(first_leading.slice().start(), f.context().source()) > 1 { write!(f, [empty_line()])?; } write!(f, [leading_comments(self.comments)])?; } else if let Some(last_preceding) = self.last_node { - let full_end = skip_trailing_trivia(last_preceding.end(), f.context().contents()); + let full_end = skip_trailing_trivia(last_preceding.end(), f.context().source()); // The leading comments formatting ensures that it preserves the right amount of lines after // We need to take care of this ourselves, if there's no leading `else` comment. - if lines_after(full_end, f.context().contents()) > 1 { + if lines_after(full_end, f.context().source()) > 1 { write!(f, [empty_line()])?; } } @@ -140,7 +140,7 @@ impl Format> for FormatTrailingComments<'_> { has_trailing_own_line_comment |= trailing.line_position().is_own_line(); if has_trailing_own_line_comment { - let lines_before_comment = lines_before(slice.start(), f.context().contents()); + let lines_before_comment = lines_before(slice.start(), f.context().source()); // A trailing comment at the end of a body or list // ```python @@ -217,7 +217,7 @@ impl Format> for FormatDanglingComments<'_> { f, [ format_comment(comment), - empty_lines(lines_after(comment.slice().end(), f.context().contents())) + empty_lines(lines_after(comment.slice().end(), f.context().source())) ] )?; @@ -245,7 +245,7 @@ struct FormatComment<'a> { impl Format> for FormatComment<'_> { fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { let slice = self.comment.slice(); - let comment_text = slice.text(SourceCode::new(f.context().contents())); + let comment_text = slice.text(SourceCode::new(f.context().source())); let trimmed = comment_text.trim_end(); let trailing_whitespace_len = comment_text.text_len() - trimmed.text_len(); diff --git a/crates/ruff_python_formatter/src/context.rs b/crates/ruff_python_formatter/src/context.rs index 2683641dd861a..d0828745c8c65 100644 --- a/crates/ruff_python_formatter/src/context.rs +++ b/crates/ruff_python_formatter/src/context.rs @@ -22,7 +22,7 @@ impl<'a> PyFormatContext<'a> { } } - pub(crate) fn contents(&self) -> &'a str { + pub(crate) fn source(&self) -> &'a str { self.contents } diff --git a/crates/ruff_python_formatter/src/expression/expr_attribute.rs b/crates/ruff_python_formatter/src/expression/expr_attribute.rs index 16ccaa330c318..2fd19d768f88e 100644 --- a/crates/ruff_python_formatter/src/expression/expr_attribute.rs +++ b/crates/ruff_python_formatter/src/expression/expr_attribute.rs @@ -97,14 +97,13 @@ impl NeedsParentheses for ExprAttribute { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - if has_breaking_comments_attribute_chain(self, comments) { + if has_breaking_comments_attribute_chain(self, context.comments()) { return Parentheses::Always; } - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } diff --git a/crates/ruff_python_formatter/src/expression/expr_await.rs b/crates/ruff_python_formatter/src/expression/expr_await.rs index 19c6bf5196a5e..c071299f84c84 100644 --- a/crates/ruff_python_formatter/src/expression/expr_await.rs +++ b/crates/ruff_python_formatter/src/expression/expr_await.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -21,9 +22,8 @@ impl NeedsParentheses for ExprAwait { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_bin_op.rs b/crates/ruff_python_formatter/src/expression/expr_bin_op.rs index 9307ed204320d..77ed14f9331bf 100644 --- a/crates/ruff_python_formatter/src/expression/expr_bin_op.rs +++ b/crates/ruff_python_formatter/src/expression/expr_bin_op.rs @@ -1,4 +1,4 @@ -use crate::comments::{trailing_comments, trailing_node_comments, Comments}; +use crate::comments::{trailing_comments, trailing_node_comments}; use crate::expression::parentheses::{ default_expression_needs_parentheses, in_parentheses_only_group, is_expression_parenthesized, NeedsParentheses, Parenthesize, @@ -7,7 +7,7 @@ use crate::expression::Parentheses; use crate::prelude::*; use crate::FormatNodeRule; use ruff_formatter::{write, FormatOwnedWithRule, FormatRefWithRule, FormatRuleWithOptions}; -use ruff_python_ast::node::AstNode; +use ruff_python_ast::expression::ExpressionRef; use rustpython_parser::ast::{ Constant, Expr, ExprAttribute, ExprBinOp, ExprConstant, ExprUnaryOp, Operator, UnaryOp, }; @@ -33,10 +33,10 @@ impl FormatNodeRule for FormatExprBinOp { let comments = f.context().comments().clone(); let format_inner = format_with(|f: &mut PyFormatter| { - let source = f.context().contents(); + let source = f.context().source(); let binary_chain: SmallVec<[&ExprBinOp; 4]> = iter::successors(Some(item), |parent| { parent.left.as_bin_op_expr().and_then(|bin_expression| { - if is_expression_parenthesized(bin_expression.as_any_node_ref(), source) { + if is_expression_parenthesized(ExpressionRef::from(bin_expression), source) { None } else { Some(bin_expression) @@ -176,9 +176,8 @@ impl NeedsParentheses for ExprBinOp { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_bool_op.rs b/crates/ruff_python_formatter/src/expression/expr_bool_op.rs index 5a350645095ce..c66d42a0704b3 100644 --- a/crates/ruff_python_formatter/src/expression/expr_bool_op.rs +++ b/crates/ruff_python_formatter/src/expression/expr_bool_op.rs @@ -1,4 +1,4 @@ -use crate::comments::{leading_comments, Comments}; +use crate::comments::{leading_comments}; use crate::expression::parentheses::{ default_expression_needs_parentheses, in_parentheses_only_group, NeedsParentheses, Parentheses, Parenthesize, @@ -71,10 +71,9 @@ impl NeedsParentheses for ExprBoolOp { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_call.rs b/crates/ruff_python_formatter/src/expression/expr_call.rs index 87ed281572c7e..4a7289f617b1e 100644 --- a/crates/ruff_python_formatter/src/expression/expr_call.rs +++ b/crates/ruff_python_formatter/src/expression/expr_call.rs @@ -1,5 +1,6 @@ use crate::builders::PyFormatterExtensions; -use crate::comments::{dangling_comments, Comments}; +use crate::comments::{dangling_comments}; +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, parenthesized, NeedsParentheses, Parentheses, Parenthesize, @@ -88,10 +89,9 @@ impl NeedsParentheses for ExprCall { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } diff --git a/crates/ruff_python_formatter/src/expression/expr_compare.rs b/crates/ruff_python_formatter/src/expression/expr_compare.rs index 10bffe948b056..23209be0ddfad 100644 --- a/crates/ruff_python_formatter/src/expression/expr_compare.rs +++ b/crates/ruff_python_formatter/src/expression/expr_compare.rs @@ -1,4 +1,4 @@ -use crate::comments::{leading_comments, Comments}; +use crate::comments::{leading_comments}; use crate::expression::parentheses::{ default_expression_needs_parentheses, in_parentheses_only_group, NeedsParentheses, Parentheses, Parenthesize, @@ -70,10 +70,9 @@ impl NeedsParentheses for ExprCompare { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_constant.rs b/crates/ruff_python_formatter/src/expression/expr_constant.rs index 68d538ae8a0ba..d64030b3b1cf3 100644 --- a/crates/ruff_python_formatter/src/expression/expr_constant.rs +++ b/crates/ruff_python_formatter/src/expression/expr_constant.rs @@ -1,4 +1,4 @@ -use crate::comments::Comments; + use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -63,10 +63,9 @@ impl NeedsParentheses for ExprConstant { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional if self.value.is_str() && parenthesize.is_if_breaks() => { // Custom handling that only adds parentheses for implicit concatenated strings. if parenthesize.is_if_breaks() { diff --git a/crates/ruff_python_formatter/src/expression/expr_dict.rs b/crates/ruff_python_formatter/src/expression/expr_dict.rs index 6299fc0845317..1f9fcca5681c9 100644 --- a/crates/ruff_python_formatter/src/expression/expr_dict.rs +++ b/crates/ruff_python_formatter/src/expression/expr_dict.rs @@ -1,4 +1,4 @@ -use crate::comments::{dangling_node_comments, leading_comments, Comments}; +use crate::comments::{dangling_node_comments, leading_comments}; use crate::expression::parentheses::{ default_expression_needs_parentheses, parenthesized, NeedsParentheses, Parentheses, Parenthesize, @@ -100,10 +100,9 @@ impl NeedsParentheses for ExprDict { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } diff --git a/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs b/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs index 4121acb76afc2..bc4b920aa4e1e 100644 --- a/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_dict_comp.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -24,10 +25,9 @@ impl NeedsParentheses for ExprDictComp { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } diff --git a/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs b/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs index ef2551de32153..9d38477f3373c 100644 --- a/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs +++ b/crates/ruff_python_formatter/src/expression/expr_formatted_value.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -19,9 +20,8 @@ impl NeedsParentheses for ExprFormattedValue { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs b/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs index 8cf7e8d38cbb4..b04fc57fb428b 100644 --- a/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_generator_exp.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -24,10 +25,9 @@ impl NeedsParentheses for ExprGeneratorExp { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } diff --git a/crates/ruff_python_formatter/src/expression/expr_if_exp.rs b/crates/ruff_python_formatter/src/expression/expr_if_exp.rs index ae142e7122277..85bcff304c2cf 100644 --- a/crates/ruff_python_formatter/src/expression/expr_if_exp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_if_exp.rs @@ -1,4 +1,4 @@ -use crate::comments::{leading_comments, Comments}; +use crate::comments::leading_comments; use crate::expression::parentheses::{ default_expression_needs_parentheses, in_parentheses_only_group, NeedsParentheses, Parentheses, Parenthesize, @@ -47,9 +47,8 @@ impl NeedsParentheses for ExprIfExp { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_joined_str.rs b/crates/ruff_python_formatter/src/expression/expr_joined_str.rs index a13ff5f38971d..ebe2fc1ec59f0 100644 --- a/crates/ruff_python_formatter/src/expression/expr_joined_str.rs +++ b/crates/ruff_python_formatter/src/expression/expr_joined_str.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -19,9 +20,8 @@ impl NeedsParentheses for ExprJoinedStr { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_lambda.rs b/crates/ruff_python_formatter/src/expression/expr_lambda.rs index bd63bfa0f63b9..faa7eeb0a4747 100644 --- a/crates/ruff_python_formatter/src/expression/expr_lambda.rs +++ b/crates/ruff_python_formatter/src/expression/expr_lambda.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -19,9 +20,8 @@ impl NeedsParentheses for ExprLambda { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_list.rs b/crates/ruff_python_formatter/src/expression/expr_list.rs index 90d5e244e1f05..c090182762025 100644 --- a/crates/ruff_python_formatter/src/expression/expr_list.rs +++ b/crates/ruff_python_formatter/src/expression/expr_list.rs @@ -1,4 +1,4 @@ -use crate::comments::{dangling_comments, CommentLinePosition, Comments}; +use crate::comments::{dangling_comments, CommentLinePosition}; use crate::expression::parentheses::{ default_expression_needs_parentheses, parenthesized, NeedsParentheses, Parentheses, Parenthesize, @@ -68,10 +68,9 @@ impl NeedsParentheses for ExprList { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } diff --git a/crates/ruff_python_formatter/src/expression/expr_list_comp.rs b/crates/ruff_python_formatter/src/expression/expr_list_comp.rs index 5bc6a3017aa0c..1c060c21aa6f9 100644 --- a/crates/ruff_python_formatter/src/expression/expr_list_comp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_list_comp.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -24,10 +25,9 @@ impl NeedsParentheses for ExprListComp { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } diff --git a/crates/ruff_python_formatter/src/expression/expr_name.rs b/crates/ruff_python_formatter/src/expression/expr_name.rs index 25673494818c8..179921d69e401 100644 --- a/crates/ruff_python_formatter/src/expression/expr_name.rs +++ b/crates/ruff_python_formatter/src/expression/expr_name.rs @@ -1,4 +1,4 @@ -use crate::comments::Comments; + use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -30,10 +30,9 @@ impl NeedsParentheses for ExprName { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_named_expr.rs b/crates/ruff_python_formatter/src/expression/expr_named_expr.rs index 71d2bae891053..365350993f2da 100644 --- a/crates/ruff_python_formatter/src/expression/expr_named_expr.rs +++ b/crates/ruff_python_formatter/src/expression/expr_named_expr.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -19,9 +20,8 @@ impl NeedsParentheses for ExprNamedExpr { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_set.rs b/crates/ruff_python_formatter/src/expression/expr_set.rs index c1b1a9009187a..015719d267058 100644 --- a/crates/ruff_python_formatter/src/expression/expr_set.rs +++ b/crates/ruff_python_formatter/src/expression/expr_set.rs @@ -1,4 +1,4 @@ -use crate::comments::Comments; + use crate::expression::parentheses::{ default_expression_needs_parentheses, parenthesized, NeedsParentheses, Parentheses, Parenthesize, @@ -31,10 +31,9 @@ impl NeedsParentheses for ExprSet { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } diff --git a/crates/ruff_python_formatter/src/expression/expr_set_comp.rs b/crates/ruff_python_formatter/src/expression/expr_set_comp.rs index d5174782e089e..b1f4dec6e5b63 100644 --- a/crates/ruff_python_formatter/src/expression/expr_set_comp.rs +++ b/crates/ruff_python_formatter/src/expression/expr_set_comp.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -24,10 +25,9 @@ impl NeedsParentheses for ExprSetComp { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } diff --git a/crates/ruff_python_formatter/src/expression/expr_slice.rs b/crates/ruff_python_formatter/src/expression/expr_slice.rs index bc4fbba2287fd..1dcf71099b9f4 100644 --- a/crates/ruff_python_formatter/src/expression/expr_slice.rs +++ b/crates/ruff_python_formatter/src/expression/expr_slice.rs @@ -1,4 +1,5 @@ -use crate::comments::{dangling_comments, Comments, SourceComment}; +use crate::comments::{dangling_comments, SourceComment}; +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -27,8 +28,7 @@ impl FormatNodeRule for FormatExprSlice { step, } = item; - let (first_colon, second_colon) = - find_colons(f.context().contents(), *range, lower, upper)?; + let (first_colon, second_colon) = find_colons(f.context().source(), *range, lower, upper)?; // Handle comment placement // In placements.rs, we marked comment for None nodes a dangling and associated all others @@ -263,9 +263,8 @@ impl NeedsParentheses for ExprSlice { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_starred.rs b/crates/ruff_python_formatter/src/expression/expr_starred.rs index 3711deb92ed2f..22d6168d8c46d 100644 --- a/crates/ruff_python_formatter/src/expression/expr_starred.rs +++ b/crates/ruff_python_formatter/src/expression/expr_starred.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -24,9 +25,8 @@ impl NeedsParentheses for ExprStarred { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_subscript.rs b/crates/ruff_python_formatter/src/expression/expr_subscript.rs index e880d69e7af76..7e87875a9655d 100644 --- a/crates/ruff_python_formatter/src/expression/expr_subscript.rs +++ b/crates/ruff_python_formatter/src/expression/expr_subscript.rs @@ -3,8 +3,9 @@ use rustpython_parser::ast::ExprSubscript; use ruff_formatter::{format_args, write}; use ruff_python_ast::node::AstNode; -use crate::comments::{trailing_comments, Comments}; +use crate::comments::trailing_comments; use crate::context::NodeLevel; +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, in_parentheses_only_group, NeedsParentheses, Parentheses, Parenthesize, @@ -67,10 +68,9 @@ impl NeedsParentheses for ExprSubscript { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } diff --git a/crates/ruff_python_formatter/src/expression/expr_tuple.rs b/crates/ruff_python_formatter/src/expression/expr_tuple.rs index de97a5bac95d7..b42b1f8604274 100644 --- a/crates/ruff_python_formatter/src/expression/expr_tuple.rs +++ b/crates/ruff_python_formatter/src/expression/expr_tuple.rs @@ -1,5 +1,5 @@ use crate::builders::optional_parentheses; -use crate::comments::{dangling_node_comments, Comments}; +use crate::comments::{dangling_node_comments}; use crate::expression::parentheses::{ default_expression_needs_parentheses, parenthesized, NeedsParentheses, Parentheses, Parenthesize, @@ -114,10 +114,9 @@ impl NeedsParentheses for ExprTuple { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => Parentheses::Never, parentheses => parentheses, } @@ -131,7 +130,7 @@ fn is_parenthesized( f: &mut Formatter>, ) -> bool { let parentheses = '('; - let first_char = &f.context().contents()[usize::from(tuple_range.start())..] + let first_char = &f.context().source()[usize::from(tuple_range.start())..] .chars() .next(); let Some(first_char) = first_char else { diff --git a/crates/ruff_python_formatter/src/expression/expr_unary_op.rs b/crates/ruff_python_formatter/src/expression/expr_unary_op.rs index 41a7feced2e0e..26134509ee2c7 100644 --- a/crates/ruff_python_formatter/src/expression/expr_unary_op.rs +++ b/crates/ruff_python_formatter/src/expression/expr_unary_op.rs @@ -1,4 +1,5 @@ -use crate::comments::{trailing_comments, Comments}; +use crate::comments::{trailing_comments}; +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -70,13 +71,12 @@ impl NeedsParentheses for ExprUnaryOp { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) { + match default_expression_needs_parentheses(self.into(), parenthesize, context) { Parentheses::Optional => { // We preserve the parentheses of the operand. It should not be necessary to break this expression. - if is_operand_parenthesized(self, source) { + if is_operand_parenthesized(self, context.source()) { Parentheses::Never } else { Parentheses::Optional diff --git a/crates/ruff_python_formatter/src/expression/expr_yield.rs b/crates/ruff_python_formatter/src/expression/expr_yield.rs index f2ece7ecac66e..212eb60a73729 100644 --- a/crates/ruff_python_formatter/src/expression/expr_yield.rs +++ b/crates/ruff_python_formatter/src/expression/expr_yield.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -19,9 +20,8 @@ impl NeedsParentheses for ExprYield { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/expr_yield_from.rs b/crates/ruff_python_formatter/src/expression/expr_yield_from.rs index bfaf10116221c..30a09b27f5298 100644 --- a/crates/ruff_python_formatter/src/expression/expr_yield_from.rs +++ b/crates/ruff_python_formatter/src/expression/expr_yield_from.rs @@ -1,4 +1,5 @@ -use crate::comments::Comments; + +use crate::context::PyFormatContext; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; @@ -19,9 +20,8 @@ impl NeedsParentheses for ExprYieldFrom { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - default_expression_needs_parentheses(self.into(), parenthesize, source, comments) + default_expression_needs_parentheses(self.into(), parenthesize, context) } } diff --git a/crates/ruff_python_formatter/src/expression/mod.rs b/crates/ruff_python_formatter/src/expression/mod.rs index 171a61a3b8c42..f5806385e3b45 100644 --- a/crates/ruff_python_formatter/src/expression/mod.rs +++ b/crates/ruff_python_formatter/src/expression/mod.rs @@ -1,15 +1,15 @@ +use std::cmp::Ordering; + use rustpython_parser::ast; use rustpython_parser::ast::{Expr, Operator}; -use std::cmp::Ordering; -use crate::builders::optional_parentheses; use ruff_formatter::{ format_args, FormatOwnedWithRule, FormatRefWithRule, FormatRule, FormatRuleWithOptions, }; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::expression::ExpressionRef; use ruff_python_ast::visitor::preorder::{walk_expr, PreorderVisitor}; -use crate::comments::Comments; +use crate::builders::optional_parentheses; use crate::context::NodeLevel; use crate::expression::expr_tuple::TupleParentheses; use crate::expression::parentheses::{ @@ -64,11 +64,7 @@ impl FormatRuleWithOptions> for FormatExpr { impl FormatRule> for FormatExpr { fn fmt(&self, item: &Expr, f: &mut PyFormatter) -> FormatResult<()> { - let parentheses = item.needs_parentheses( - self.parenthesize, - f.context().contents(), - f.context().comments(), - ); + let parentheses = item.needs_parentheses(self.parenthesize, f.context()); let format_expr = format_with(|f| match item { Expr::BoolOp(expr) => expr.format().with_options(Some(parentheses)).fmt(f), @@ -165,37 +161,36 @@ impl NeedsParentheses for Expr { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { match self { - Expr::BoolOp(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::NamedExpr(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::BinOp(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::UnaryOp(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Lambda(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::IfExp(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Dict(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Set(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::ListComp(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::SetComp(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::DictComp(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::GeneratorExp(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Await(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Yield(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::YieldFrom(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Compare(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Call(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::FormattedValue(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::JoinedStr(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Constant(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Attribute(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Subscript(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Starred(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Name(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::List(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Tuple(expr) => expr.needs_parentheses(parenthesize, source, comments), - Expr::Slice(expr) => expr.needs_parentheses(parenthesize, source, comments), + Expr::BoolOp(expr) => expr.needs_parentheses(parenthesize, context), + Expr::NamedExpr(expr) => expr.needs_parentheses(parenthesize, context), + Expr::BinOp(expr) => expr.needs_parentheses(parenthesize, context), + Expr::UnaryOp(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Lambda(expr) => expr.needs_parentheses(parenthesize, context), + Expr::IfExp(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Dict(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Set(expr) => expr.needs_parentheses(parenthesize, context), + Expr::ListComp(expr) => expr.needs_parentheses(parenthesize, context), + Expr::SetComp(expr) => expr.needs_parentheses(parenthesize, context), + Expr::DictComp(expr) => expr.needs_parentheses(parenthesize, context), + Expr::GeneratorExp(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Await(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Yield(expr) => expr.needs_parentheses(parenthesize, context), + Expr::YieldFrom(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Compare(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Call(expr) => expr.needs_parentheses(parenthesize, context), + Expr::FormattedValue(expr) => expr.needs_parentheses(parenthesize, context), + Expr::JoinedStr(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Constant(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Attribute(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Subscript(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Starred(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Name(expr) => expr.needs_parentheses(parenthesize, context), + Expr::List(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Tuple(expr) => expr.needs_parentheses(parenthesize, context), + Expr::Slice(expr) => expr.needs_parentheses(parenthesize, context), } } } @@ -224,19 +219,24 @@ impl<'ast> IntoFormat> for Expr { /// `(a * b) * c` or `a * b + c` are okay, because the subexpression is parenthesized, or the expression uses operands with a lower priority /// * The expression contains at least one parenthesized sub expression (optimization to avoid unnecessary work) fn can_omit_optional_parentheses(expr: &Expr, context: &PyFormatContext) -> bool { - let mut visitor = MaxOperatorPriorityVisitor::new(context.contents()); + if context.comments().has_leading_comments(expr) { + false + } else { + let mut visitor = MaxOperatorPriorityVisitor::new(context.source()); - visitor.visit_subexpression(expr); + visitor.visit_subexpression(expr); - let (max_operator_priority, operation_count, any_parenthesized_expression) = visitor.finish(); + let (max_operator_priority, operation_count, any_parenthesized_expression) = + visitor.finish(); - if operation_count > 1 { - false - } else if max_operator_priority == OperatorPriority::Attribute { - true - } else { - // Only use the more complex IR when there is any expression that we can possibly split by - any_parenthesized_expression + if operation_count > 1 { + false + } else if max_operator_priority == OperatorPriority::Attribute { + true + } else { + // Only use the more complex IR when there is any expression that we can possibly split by + any_parenthesized_expression + } } } @@ -383,7 +383,7 @@ impl<'input> MaxOperatorPriorityVisitor<'input> { impl<'input> PreorderVisitor<'input> for MaxOperatorPriorityVisitor<'input> { fn visit_expr(&mut self, expr: &'input Expr) { // Rule only applies for non-parenthesized expressions. - if is_expression_parenthesized(AnyNodeRef::from(expr), self.source) { + if is_expression_parenthesized(ExpressionRef::from(expr), self.source) { self.any_parenthesized_expressions = true; } else { self.visit_subexpression(expr); @@ -403,7 +403,7 @@ fn has_parentheses(expr: &Expr, source: &str) -> bool { | Expr::DictComp(_) | Expr::Call(_) | Expr::Subscript(_) - ) || is_expression_parenthesized(AnyNodeRef::from(expr), source) + ) || is_expression_parenthesized(ExpressionRef::from(expr), source) } #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] diff --git a/crates/ruff_python_formatter/src/expression/parentheses.rs b/crates/ruff_python_formatter/src/expression/parentheses.rs index 670293e744eb6..640ecf1c33ffc 100644 --- a/crates/ruff_python_formatter/src/expression/parentheses.rs +++ b/crates/ruff_python_formatter/src/expression/parentheses.rs @@ -1,32 +1,24 @@ -use crate::comments::Comments; use crate::context::NodeLevel; use crate::prelude::*; use crate::trivia::{first_non_trivia_token, first_non_trivia_token_rev, Token, TokenKind}; use ruff_formatter::prelude::tag::Condition; use ruff_formatter::{format_args, Argument, Arguments}; -use ruff_python_ast::node::AnyNodeRef; +use ruff_python_ast::expression::ExpressionRef; use rustpython_parser::ast::Ranged; pub(crate) trait NeedsParentheses { fn needs_parentheses( &self, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses; } pub(super) fn default_expression_needs_parentheses( - node: AnyNodeRef, + node: ExpressionRef, parenthesize: Parenthesize, - source: &str, - comments: &Comments, + context: &PyFormatContext, ) -> Parentheses { - debug_assert!( - node.is_expression(), - "Should only be called for expressions" - ); - #[allow(clippy::if_same_then_else)] if parenthesize.is_always() { Parentheses::Always @@ -34,13 +26,13 @@ pub(super) fn default_expression_needs_parentheses( Parentheses::Never } // `Optional` or `Preserve` and expression has parentheses in source code. - else if !parenthesize.is_if_breaks() && is_expression_parenthesized(node, source) { + else if !parenthesize.is_if_breaks() && is_expression_parenthesized(node, context.source()) { Parentheses::Always } // `Optional` or `IfBreaks`: Add parentheses if the expression doesn't fit on a line but enforce // parentheses if the expression has leading comments else if !parenthesize.is_preserve() { - if comments.has_leading_comments(node) { + if context.comments().has_leading_comments(node) { Parentheses::Always } else { Parentheses::Optional @@ -108,7 +100,7 @@ pub enum Parentheses { Never, } -pub(crate) fn is_expression_parenthesized(expr: AnyNodeRef, contents: &str) -> bool { +pub(crate) fn is_expression_parenthesized(expr: ExpressionRef, contents: &str) -> bool { matches!( first_non_trivia_token(expr.end(), contents), Some(Token { diff --git a/crates/ruff_python_formatter/src/other/arguments.rs b/crates/ruff_python_formatter/src/other/arguments.rs index 0682a25632c48..3e84558ad2c6a 100644 --- a/crates/ruff_python_formatter/src/other/arguments.rs +++ b/crates/ruff_python_formatter/src/other/arguments.rs @@ -36,7 +36,7 @@ impl FormatNodeRule for FormatArguments { let comments = f.context().comments().clone(); let dangling = comments.dangling_comments(item); - let (slash, star) = find_argument_separators(f.context().contents(), item); + let (slash, star) = find_argument_separators(f.context().source(), item); let format_inner = format_with(|f: &mut PyFormatter| { let separator = format_with(|f| write!(f, [text(","), soft_line_break_or_space()])); @@ -142,7 +142,7 @@ impl FormatNodeRule for FormatArguments { let maybe_comma_token = if ends_with_pos_only_argument_separator { // `def a(b, c, /): ... ` let mut tokens = - SimpleTokenizer::starts_at(last_node.end(), f.context().contents()) + SimpleTokenizer::starts_at(last_node.end(), f.context().source()) .skip_trivia(); let comma = tokens.next(); @@ -153,7 +153,7 @@ impl FormatNodeRule for FormatArguments { tokens.next() } else { - first_non_trivia_token(last_node.end(), f.context().contents()) + first_non_trivia_token(last_node.end(), f.context().source()) }; if maybe_comma_token.map_or(false, |token| token.kind() == TokenKind::Comma) { diff --git a/crates/ruff_python_formatter/src/statement/stmt_class_def.rs b/crates/ruff_python_formatter/src/statement/stmt_class_def.rs index 3fba6d4a55e9b..2388323ae1333 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_class_def.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_class_def.rs @@ -79,7 +79,7 @@ impl Format> for FormatInheritanceClause<'_> { .. } = self.class_definition; - let source = f.context().contents(); + let source = f.context().source(); let mut joiner = f.join_comma_separated(); diff --git a/crates/ruff_python_formatter/src/statement/stmt_expr.rs b/crates/ruff_python_formatter/src/statement/stmt_expr.rs index b0c451fa6a6df..753d4dbc928cb 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_expr.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_expr.rs @@ -2,6 +2,7 @@ use crate::expression::parentheses::{is_expression_parenthesized, Parenthesize}; use crate::expression::string::StringLayout; use crate::prelude::*; use crate::FormatNodeRule; +use ruff_python_ast::expression::ExpressionRef; use rustpython_parser::ast::StmtExpr; #[derive(Default)] @@ -13,7 +14,10 @@ impl FormatNodeRule for FormatStmtExpr { if let Some(constant) = value.as_constant_expr() { if constant.value.is_str() - && !is_expression_parenthesized(value.as_ref().into(), f.context().contents()) + && !is_expression_parenthesized( + ExpressionRef::from(value.as_ref()), + f.context().source(), + ) { return constant.format().with_options(StringLayout::Flat).fmt(f); } diff --git a/crates/ruff_python_formatter/src/statement/stmt_function_def.rs b/crates/ruff_python_formatter/src/statement/stmt_function_def.rs index 491429b2afa1f..55439fd35b00a 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_function_def.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_function_def.rs @@ -56,9 +56,9 @@ impl FormatRule, PyFormatContext<'_>> for FormatAnyFun // while maintaining the right amount of empty lines between the comment // and the last decorator. let decorator_end = - skip_trailing_trivia(last_decorator.end(), f.context().contents()); + skip_trailing_trivia(last_decorator.end(), f.context().source()); - let leading_line = if lines_after(decorator_end, f.context().contents()) <= 1 { + let leading_line = if lines_after(decorator_end, f.context().source()) <= 1 { hard_line_break() } else { empty_line() diff --git a/crates/ruff_python_formatter/src/statement/suite.rs b/crates/ruff_python_formatter/src/statement/suite.rs index be25b63399bc0..92fc32ed4e601 100644 --- a/crates/ruff_python_formatter/src/statement/suite.rs +++ b/crates/ruff_python_formatter/src/statement/suite.rs @@ -43,7 +43,7 @@ impl FormatRule> for FormatSuite { }; let comments = f.context().comments().clone(); - let source = f.context().contents(); + let source = f.context().source(); let saved_level = f.context().node_level(); f.context_mut().set_node_level(node_level);