diff --git a/crates/ruff_python_formatter/src/context.rs b/crates/ruff_python_formatter/src/context.rs index eb8fe7edf4155..2e6cdc0d2ed51 100644 --- a/crates/ruff_python_formatter/src/context.rs +++ b/crates/ruff_python_formatter/src/context.rs @@ -74,6 +74,11 @@ impl<'a> PyFormatContext<'a> { ..self } } + + /// Returns `true` if preview mode is enabled. + pub(crate) const fn is_preview(&self) -> bool { + self.options.preview().is_enabled() + } } impl FormatContext for PyFormatContext<'_> { diff --git a/crates/ruff_python_formatter/src/expression/binary_like.rs b/crates/ruff_python_formatter/src/expression/binary_like.rs index 149449d61cb04..9a9feea584831 100644 --- a/crates/ruff_python_formatter/src/expression/binary_like.rs +++ b/crates/ruff_python_formatter/src/expression/binary_like.rs @@ -3,7 +3,7 @@ use std::ops::{Deref, Index}; use smallvec::SmallVec; -use ruff_formatter::{write, FormatContext}; +use ruff_formatter::write; use ruff_python_ast::{ Expr, ExprAttribute, ExprBinOp, ExprBoolOp, ExprCompare, ExprUnaryOp, UnaryOp, }; @@ -21,6 +21,7 @@ use crate::expression::parentheses::{ use crate::expression::string::{AnyString, FormatString, StringLayout}; use crate::expression::OperatorPrecedence; use crate::prelude::*; +use crate::preview::is_fix_power_op_line_length_enabled; #[derive(Copy, Clone, Debug)] pub(super) enum BinaryLike<'a> { @@ -719,7 +720,7 @@ impl Format> for FlatBinaryExpressionSlice<'_> { { hard_line_break().fmt(f)?; } else if is_pow { - if f.context().options().preview().is_enabled() { + if is_fix_power_op_line_length_enabled(f.context()) { in_parentheses_only_if_group_breaks(&space()).fmt(f)?; } } else { diff --git a/crates/ruff_python_formatter/src/expression/mod.rs b/crates/ruff_python_formatter/src/expression/mod.rs index 06cbe3bc2cebd..1fb97009e4b64 100644 --- a/crates/ruff_python_formatter/src/expression/mod.rs +++ b/crates/ruff_python_formatter/src/expression/mod.rs @@ -21,7 +21,7 @@ use crate::expression::parentheses::{ OptionalParentheses, Parentheses, Parenthesize, }; use crate::prelude::*; -use crate::PyFormatOptions; +use crate::preview::is_hug_parens_with_braces_and_square_brackets_enabled; mod binary_like; pub(crate) mod expr_attribute; @@ -129,7 +129,7 @@ impl FormatRule> for FormatExpr { let node_comments = comments.leading_dangling_trailing(expression); if !node_comments.has_leading() && !node_comments.has_trailing() { parenthesized("(", &format_expr, ")") - .with_indent(!is_expression_huggable(expression, f.options())) + .with_indent(!is_expression_huggable(expression, f.context())) .fmt(f) } else { format_with_parentheses_comments(expression, &node_comments, f) @@ -448,7 +448,7 @@ impl Format> for MaybeParenthesizeExpression<'_> { OptionalParentheses::Never => match parenthesize { Parenthesize::IfBreaksOrIfRequired => { parenthesize_if_expands(&expression.format().with_options(Parentheses::Never)) - .with_indent(!is_expression_huggable(expression, f.options())) + .with_indent(!is_expression_huggable(expression, f.context())) .fmt(f) } @@ -1061,8 +1061,8 @@ pub(crate) fn has_own_parentheses( /// ] /// ) /// ``` -pub(crate) fn is_expression_huggable(expr: &Expr, options: &PyFormatOptions) -> bool { - if !options.preview().is_enabled() { +pub(crate) fn is_expression_huggable(expr: &Expr, context: &PyFormatContext) -> bool { + if !is_hug_parens_with_braces_and_square_brackets_enabled(context) { return false; } diff --git a/crates/ruff_python_formatter/src/lib.rs b/crates/ruff_python_formatter/src/lib.rs index e9a3c34757da9..ce3988dd54693 100644 --- a/crates/ruff_python_formatter/src/lib.rs +++ b/crates/ruff_python_formatter/src/lib.rs @@ -32,6 +32,7 @@ mod options; pub(crate) mod other; pub(crate) mod pattern; mod prelude; +mod preview; mod shared_traits; pub(crate) mod statement; pub(crate) mod type_param; diff --git a/crates/ruff_python_formatter/src/options.rs b/crates/ruff_python_formatter/src/options.rs index 261dfeab190ff..8306afd82c431 100644 --- a/crates/ruff_python_formatter/src/options.rs +++ b/crates/ruff_python_formatter/src/options.rs @@ -119,7 +119,7 @@ impl PyFormatOptions { self.docstring_code } - pub fn preview(&self) -> PreviewMode { + pub const fn preview(&self) -> PreviewMode { self.preview } diff --git a/crates/ruff_python_formatter/src/other/arguments.rs b/crates/ruff_python_formatter/src/other/arguments.rs index a48596cac0eb3..d57e168c89459 100644 --- a/crates/ruff_python_formatter/src/other/arguments.rs +++ b/crates/ruff_python_formatter/src/other/arguments.rs @@ -9,6 +9,7 @@ use crate::expression::is_expression_huggable; use crate::expression::parentheses::{empty_parenthesized, parenthesized, Parentheses}; use crate::other::commas; use crate::prelude::*; +use crate::preview::is_hug_parens_with_braces_and_square_brackets_enabled; #[derive(Default)] pub struct FormatArguments; @@ -177,8 +178,7 @@ fn is_single_argument_parenthesized(argument: &Expr, call_end: TextSize, source: /// Hugging should only be applied to single-argument collections, like lists, or starred versions /// of those collections. fn is_argument_huggable(item: &Arguments, context: &PyFormatContext) -> bool { - let options = context.options(); - if !options.preview().is_enabled() { + if !is_hug_parens_with_braces_and_square_brackets_enabled(context) { return false; } @@ -192,7 +192,7 @@ fn is_argument_huggable(item: &Arguments, context: &PyFormatContext) -> bool { }; // If the expression itself isn't huggable, then we can't hug it. - if !is_expression_huggable(arg, options) { + if !is_expression_huggable(arg, context) { return false; } @@ -202,6 +202,8 @@ fn is_argument_huggable(item: &Arguments, context: &PyFormatContext) -> bool { return false; } + let options = context.options(); + // If the expression has a trailing comma, then we can't hug it. if options.magic_trailing_comma().is_respect() && commas::has_magic_trailing_comma(TextRange::new(arg.end(), item.end()), options, context) diff --git a/crates/ruff_python_formatter/src/preview.rs b/crates/ruff_python_formatter/src/preview.rs new file mode 100644 index 0000000000000..8354e83a64d4a --- /dev/null +++ b/crates/ruff_python_formatter/src/preview.rs @@ -0,0 +1,19 @@ +//! Helpers to test if a specific preview style is enabled or not. +//! +//! The motivation for these functions isn't to avoid code duplication but to ease promoting preview styles +//! to stable. The challenge with directly using [`is_preview`](PyFormatContext::is_preview) is that it is unclear +//! for which specific feature this preview check is for. Having named functions simplifies the promotion: +//! Simply delete the function and let Rust tell you which checks you have to remove. +use crate::PyFormatContext; + +/// Returns `true` if the [`fix_power_op_line_length`](https://github.com/astral-sh/ruff/issues/8938) preview style is enabled. +pub(crate) const fn is_fix_power_op_line_length_enabled(context: &PyFormatContext) -> bool { + context.is_preview() +} + +/// Returns `true` if the [`hug_parens_with_braces_and_square_brackets`](https://github.com/astral-sh/ruff/issues/8279) preview style is enabled. +pub(crate) const fn is_hug_parens_with_braces_and_square_brackets_enabled( + context: &PyFormatContext, +) -> bool { + context.is_preview() +}