diff --git a/crates/ruff_formatter/src/builders.rs b/crates/ruff_formatter/src/builders.rs index fdf87e6327daf..8bb0b6933c2a2 100644 --- a/crates/ruff_formatter/src/builders.rs +++ b/crates/ruff_formatter/src/builders.rs @@ -1451,11 +1451,12 @@ impl std::fmt::Debug for Group<'_, Context> { } } -/// Content that may get parenthesized if it exceeds the configured line width but only if the parenthesized -/// layout doesn't exceed the line width too, in which case it falls back to the flat layout. +/// Content that may get parenthesized if it exceeds the configured line width but only if the parenthesized content +/// doesn't exceed the line width too, in which case it falls back to the flat layout. /// -/// This IR is identical to the following [`best_fitting`] layout but is implemented as custom IR for -/// best performance. +/// This IR is almost identical to the following [`best_fitting`] layout but is implemented as custom IR for +/// best performance. It differs in that the open parentheses is ignored when testing if the content fits because +/// the goal is to only parenthesize the content if parenthesizing makes the content fit. /// /// ```rust /// # use ruff_formatter::prelude::*; diff --git a/crates/ruff_formatter/src/printer/mod.rs b/crates/ruff_formatter/src/printer/mod.rs index e35c44ec28ef2..d9f5f61e8dfca 100644 --- a/crates/ruff_formatter/src/printer/mod.rs +++ b/crates/ruff_formatter/src/printer/mod.rs @@ -203,7 +203,9 @@ impl<'a> Printer<'a> { args.with_measure_mode(MeasureMode::AllLines), ); - queue.extend_back(&[OPEN_PAREN, INDENT, HARD_LINE_BREAK]); + // Don't measure the opening parentheses. Only concerned whether parenthesizing + // makes the content fit. + queue.extend_back(&[INDENT, HARD_LINE_BREAK]); let fits_expanded = self.fits(queue, stack)?; queue.pop_slice(); stack.pop(TagKind::BestFitParenthesize)?; @@ -1299,10 +1301,11 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> { self.state.line_width = 0; self.state.pending_indent = unindented.indention(); - return Ok(self.fits_text(Text::Token(")"), unindented)); + // Don't measure the `)` similar to the open parentheses but increment the line width and indent level. + self.fits_text(Text::Token(")"), unindented); + } else { + self.stack.pop(TagKind::BestFitParenthesize)?; } - - self.stack.pop(TagKind::BestFitParenthesize)?; } FormatElement::Tag(StartConditionalGroup(group)) => { diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/type_alias.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/type_alias.py index 8e29cd3730c9c..ad13b9d84cd6e 100644 --- a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/type_alias.py +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/type_alias.py @@ -16,10 +16,12 @@ type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[Aaaaaaaaaaaaaaaaaaaaaaaaaaaa] = int type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[Aaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbb] = int type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt # with comment # long value type X = Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt type X = Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | Ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +type XXXXXXXXXXXXX = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt # with comment # soft keyword as alias name type type = int diff --git a/crates/ruff_python_formatter/src/expression/mod.rs b/crates/ruff_python_formatter/src/expression/mod.rs index b9dc9e8520a04..06cbe3bc2cebd 100644 --- a/crates/ruff_python_formatter/src/expression/mod.rs +++ b/crates/ruff_python_formatter/src/expression/mod.rs @@ -12,9 +12,7 @@ use ruff_python_trivia::CommentRanges; use ruff_text_size::Ranged; use crate::builders::parenthesize_if_expands; -use crate::comments::{ - leading_comments, trailing_comments, LeadingDanglingTrailingComments, SourceComment, -}; +use crate::comments::{leading_comments, trailing_comments, LeadingDanglingTrailingComments}; use crate::context::{NodeLevel, WithNodeLevel}; use crate::expression::expr_generator_exp::is_generator_parenthesized; use crate::expression::expr_tuple::is_tuple_parenthesized; @@ -434,106 +432,16 @@ impl Format> for MaybeParenthesizeExpression<'_> { } Parenthesize::IfBreaks => { - // Is the expression the last token in the parent statement. - // Excludes `await` and `yield` for which Black doesn't seem to apply the layout? - let last_expression = parent.is_stmt_assign() - || parent.is_stmt_ann_assign() - || parent.is_stmt_aug_assign() - || parent.is_stmt_return(); - - // Format the statements and value's trailing end of line comments: - // * after the expression if the expression needs no parentheses (necessary or the `expand_parent` makes the group never fit). - // * inside the parentheses if the expression exceeds the line-width. - // - // ```python - // a = long # with_comment - // b = ( - // short # with_comment - // ) - // - // # formatted - // a = ( - // long # with comment - // ) - // b = short # with comment - // ``` - // This matches Black's formatting with the exception that ruff applies this style also for - // attribute chains and non-fluent call expressions. See https://github.com/psf/black/issues/4001#issuecomment-1786681792 - // - // This logic isn't implemented in [`place_comment`] by associating trailing statement comments to the expression because - // doing so breaks the suite empty lines formatting that relies on trailing comments to be stored on the statement. - let (inline_comments, expression_trailing_comments) = if last_expression - && !( - // Ignore non-fluent attribute chains for black compatibility. - // See https://github.com/psf/black/issues/4001#issuecomment-1786681792 - expression.is_attribute_expr() - || expression.is_call_expr() - || expression.is_yield_from_expr() - || expression.is_yield_expr() - || expression.is_await_expr() - ) { - let parent_trailing_comments = comments.trailing(*parent); - let after_end_of_line = parent_trailing_comments - .partition_point(|comment| comment.line_position().is_end_of_line()); - let (stmt_inline_comments, _) = - parent_trailing_comments.split_at(after_end_of_line); - - let after_end_of_line = node_comments - .trailing - .partition_point(|comment| comment.line_position().is_end_of_line()); - - let (expression_inline_comments, expression_trailing_comments) = - node_comments.trailing.split_at(after_end_of_line); - - ( - OptionalParenthesesInlinedComments { - expression: expression_inline_comments, - statement: stmt_inline_comments, - }, - expression_trailing_comments, - ) + if node_comments.has_trailing() { + expression.format().with_options(Parentheses::Always).fmt(f) } else { - ( - OptionalParenthesesInlinedComments::default(), - node_comments.trailing, - ) - }; - - if expression_trailing_comments.is_empty() { // The group id is necessary because the nested expressions may reference it. let group_id = f.group_id("optional_parentheses"); let f = &mut WithNodeLevel::new(NodeLevel::Expression(Some(group_id)), f); - best_fit_parenthesize(&format_with(|f| { - inline_comments.mark_formatted(); - - expression - .format() - .with_options(Parentheses::Never) - .fmt(f)?; - - if !inline_comments.is_empty() { - // If the expressions exceeds the line width, format the comments in the parentheses - if_group_breaks(&inline_comments) - .with_group_id(Some(group_id)) - .fmt(f)?; - } - - Ok(()) - })) - .with_group_id(Some(group_id)) - .fmt(f)?; - - if !inline_comments.is_empty() { - // If the line fits into the line width, format the comments after the parenthesized expression - if_group_fits_on_line(&inline_comments) - .with_group_id(Some(group_id)) - .fmt(f)?; - } - - Ok(()) - } else { - expression.format().with_options(Parentheses::Always).fmt(f) + best_fit_parenthesize(&expression.format().with_options(Parentheses::Never)) + .with_group_id(Some(group_id)) + .fmt(f) } } }, @@ -1248,41 +1156,3 @@ impl From for OperatorPrecedence { } } } - -#[derive(Debug, Default)] -struct OptionalParenthesesInlinedComments<'a> { - expression: &'a [SourceComment], - statement: &'a [SourceComment], -} - -impl<'a> OptionalParenthesesInlinedComments<'a> { - fn is_empty(&self) -> bool { - self.expression.is_empty() && self.statement.is_empty() - } - - fn iter_comments(&self) -> impl Iterator { - self.expression.iter().chain(self.statement) - } - - fn mark_formatted(&self) { - for comment in self.iter_comments() { - comment.mark_formatted(); - } - } -} - -impl Format> for OptionalParenthesesInlinedComments<'_> { - fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { - for comment in self.iter_comments() { - comment.mark_unformatted(); - } - - write!( - f, - [ - trailing_comments(self.expression), - trailing_comments(self.statement) - ] - ) - } -} diff --git a/crates/ruff_python_formatter/src/statement/stmt_ann_assign.rs b/crates/ruff_python_formatter/src/statement/stmt_ann_assign.rs index cb5f5fa745278..17efcab1a8f77 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_ann_assign.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_ann_assign.rs @@ -2,10 +2,8 @@ use ruff_formatter::write; use ruff_python_ast::StmtAnnAssign; use crate::comments::{SourceComment, SuppressionKind}; - -use crate::expression::maybe_parenthesize_expression; -use crate::expression::parentheses::Parenthesize; use crate::prelude::*; +use crate::statement::stmt_assign::FormatStatementsLastExpression; use crate::statement::trailing_semicolon; #[derive(Default)] @@ -33,7 +31,7 @@ impl FormatNodeRule for FormatStmtAnnAssign { space(), token("="), space(), - maybe_parenthesize_expression(value, item, Parenthesize::IfBreaks) + FormatStatementsLastExpression::new(value, item) ] )?; } diff --git a/crates/ruff_python_formatter/src/statement/stmt_assign.rs b/crates/ruff_python_formatter/src/statement/stmt_assign.rs index 7a8a5fd2be005..5044e450bbee0 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_assign.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_assign.rs @@ -1,9 +1,11 @@ use ruff_formatter::{format_args, write, FormatError}; -use ruff_python_ast::{Expr, StmtAssign}; +use ruff_python_ast::{AnyNodeRef, Expr, StmtAssign}; -use crate::comments::{SourceComment, SuppressionKind}; +use crate::comments::{trailing_comments, SourceComment, SuppressionKind}; use crate::context::{NodeLevel, WithNodeLevel}; -use crate::expression::parentheses::{Parentheses, Parenthesize}; +use crate::expression::parentheses::{ + NeedsParentheses, OptionalParentheses, Parentheses, Parenthesize, +}; use crate::expression::{has_own_parentheses, maybe_parenthesize_expression}; use crate::prelude::*; use crate::statement::trailing_semicolon; @@ -34,14 +36,7 @@ impl FormatNodeRule for FormatStmtAssign { ] )?; - write!( - f, - [maybe_parenthesize_expression( - value, - item, - Parenthesize::IfBreaks - )] - )?; + FormatStatementsLastExpression::new(value, item).fmt(f)?; if f.options().source_type().is_ipynb() && f.context().node_level().is_last_top_level_statement() @@ -133,3 +128,188 @@ enum ParenthesizeTarget { Never, IfBreaks, } + +/// Formats the last expression in statements that start with a keyword (like `return`) or after an operator (assignments). +/// +/// It avoids parenthesizing unsplittable values (like `None`, `True`, `False`, Names, a subset of strings) just to make +/// the trailing comment fit and inlines a trailing comment if the value itself exceeds the configured line width: +/// +/// The implementation formats the statement's and value's trailing end of line comments: +/// * after the expression if the expression needs no parentheses (necessary or the `expand_parent` makes the group never fit). +/// * inside the parentheses if the expression exceeds the line-width. +/// +/// ```python +/// a = loooooooooooooooooooooooooooong # with_comment +/// b = ( +/// short # with_comment +/// ) +/// ``` +/// +/// Which gets formatted to: +/// +/// ```python +/// # formatted +/// a = ( +/// loooooooooooooooooooooooooooong # with comment +/// ) +/// b = short # with comment +/// ``` +/// +/// The long name gets parenthesized because it exceeds the configured line width and the trailing comma of the +/// statement gets formatted inside (instead of outside) the parentheses. +/// +/// The `short` name gets unparenthesized because it fits into the configured line length, regardless of whether +/// the comment exceeds the line width or not. +/// +/// This logic isn't implemented in [`place_comment`] by associating trailing statement comments to the expression because +/// doing so breaks the suite empty lines formatting that relies on trailing comments to be stored on the statement. +pub(super) struct FormatStatementsLastExpression<'a> { + expression: &'a Expr, + parent: AnyNodeRef<'a>, +} + +impl<'a> FormatStatementsLastExpression<'a> { + pub(super) fn new>>(expression: &'a Expr, parent: P) -> Self { + Self { + expression, + parent: parent.into(), + } + } +} + +impl Format> for FormatStatementsLastExpression<'_> { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + let can_inline_comment = match self.expression { + Expr::Name(_) + | Expr::NoneLiteral(_) + | Expr::NumberLiteral(_) + | Expr::BooleanLiteral(_) => true, + Expr::StringLiteral(string) => { + string.needs_parentheses(self.parent, f.context()) == OptionalParentheses::BestFit + } + Expr::BytesLiteral(bytes) => { + bytes.needs_parentheses(self.parent, f.context()) == OptionalParentheses::BestFit + } + Expr::FString(fstring) => { + fstring.needs_parentheses(self.parent, f.context()) == OptionalParentheses::BestFit + } + _ => false, + }; + + if !can_inline_comment { + return maybe_parenthesize_expression( + self.expression, + self.parent, + Parenthesize::IfBreaks, + ) + .fmt(f); + } + + let comments = f.context().comments().clone(); + let expression_comments = comments.leading_dangling_trailing(self.expression); + + if expression_comments.has_leading() { + // Preserve the parentheses if the expression has any leading comments, + // same as `maybe_parenthesize_expression` + return self + .expression + .format() + .with_options(Parentheses::Always) + .fmt(f); + } + + let statement_trailing_comments = comments.trailing(self.parent); + let after_end_of_line = statement_trailing_comments + .partition_point(|comment| comment.line_position().is_end_of_line()); + let (stmt_inline_comments, _) = statement_trailing_comments.split_at(after_end_of_line); + + let after_end_of_line = expression_comments + .trailing + .partition_point(|comment| comment.line_position().is_end_of_line()); + + let (expression_inline_comments, expression_trailing_comments) = + expression_comments.trailing.split_at(after_end_of_line); + + if expression_trailing_comments.is_empty() { + let inline_comments = OptionalParenthesesInlinedComments { + expression: expression_inline_comments, + statement: stmt_inline_comments, + }; + + let group_id = f.group_id("optional_parentheses"); + let f = &mut WithNodeLevel::new(NodeLevel::Expression(Some(group_id)), f); + + best_fit_parenthesize(&format_with(|f| { + inline_comments.mark_formatted(); + + self.expression + .format() + .with_options(Parentheses::Never) + .fmt(f)?; + + if !inline_comments.is_empty() { + // If the expressions exceeds the line width, format the comments in the parentheses + if_group_breaks(&inline_comments) + .with_group_id(Some(group_id)) + .fmt(f)?; + } + + Ok(()) + })) + .with_group_id(Some(group_id)) + .fmt(f)?; + + if !inline_comments.is_empty() { + // If the line fits into the line width, format the comments after the parenthesized expression + if_group_fits_on_line(&inline_comments) + .with_group_id(Some(group_id)) + .fmt(f)?; + } + + Ok(()) + } else { + self.expression + .format() + .with_options(Parentheses::Always) + .fmt(f) + } + } +} + +#[derive(Debug, Default)] +struct OptionalParenthesesInlinedComments<'a> { + expression: &'a [SourceComment], + statement: &'a [SourceComment], +} + +impl<'a> OptionalParenthesesInlinedComments<'a> { + fn is_empty(&self) -> bool { + self.expression.is_empty() && self.statement.is_empty() + } + + fn iter_comments(&self) -> impl Iterator { + self.expression.iter().chain(self.statement) + } + + fn mark_formatted(&self) { + for comment in self.expression { + comment.mark_formatted(); + } + } +} + +impl Format> for OptionalParenthesesInlinedComments<'_> { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + for comment in self.iter_comments() { + comment.mark_unformatted(); + } + + write!( + f, + [ + trailing_comments(self.expression), + trailing_comments(self.statement) + ] + ) + } +} diff --git a/crates/ruff_python_formatter/src/statement/stmt_aug_assign.rs b/crates/ruff_python_formatter/src/statement/stmt_aug_assign.rs index 65260c5fecdc9..19202ecf0f982 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_aug_assign.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_aug_assign.rs @@ -2,10 +2,8 @@ use ruff_formatter::write; use ruff_python_ast::StmtAugAssign; use crate::comments::{SourceComment, SuppressionKind}; - -use crate::expression::maybe_parenthesize_expression; -use crate::expression::parentheses::Parenthesize; use crate::prelude::*; +use crate::statement::stmt_assign::FormatStatementsLastExpression; use crate::statement::trailing_semicolon; use crate::{AsFormat, FormatNodeRule}; @@ -28,7 +26,7 @@ impl FormatNodeRule for FormatStmtAugAssign { op.format(), token("="), space(), - maybe_parenthesize_expression(value, item, Parenthesize::IfBreaks) + FormatStatementsLastExpression::new(value, item) ] )?; diff --git a/crates/ruff_python_formatter/src/statement/stmt_return.rs b/crates/ruff_python_formatter/src/statement/stmt_return.rs index be63db2e73f2b..b0c5253e0fa38 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_return.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_return.rs @@ -3,9 +3,8 @@ use ruff_python_ast::{Expr, StmtReturn}; use crate::comments::{SourceComment, SuppressionKind}; use crate::expression::expr_tuple::TupleParentheses; -use crate::expression::maybe_parenthesize_expression; -use crate::expression::parentheses::Parenthesize; use crate::prelude::*; +use crate::statement::stmt_assign::FormatStatementsLastExpression; #[derive(Default)] pub struct FormatStmtReturn; @@ -31,10 +30,7 @@ impl FormatNodeRule for FormatStmtReturn { Some(value) => { write!( f, - [ - space(), - maybe_parenthesize_expression(value, item, Parenthesize::IfBreaks) - ] + [space(), FormatStatementsLastExpression::new(value, item)] ) } None => Ok(()), diff --git a/crates/ruff_python_formatter/src/statement/stmt_type_alias.rs b/crates/ruff_python_formatter/src/statement/stmt_type_alias.rs index c2daaf8528d20..6376236afb7d1 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_type_alias.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_type_alias.rs @@ -2,9 +2,8 @@ use ruff_formatter::write; use ruff_python_ast::StmtTypeAlias; use crate::comments::{SourceComment, SuppressionKind}; -use crate::expression::maybe_parenthesize_expression; -use crate::expression::parentheses::Parenthesize; use crate::prelude::*; +use crate::statement::stmt_assign::FormatStatementsLastExpression; #[derive(Default)] pub struct FormatStmtTypeAlias; @@ -30,7 +29,7 @@ impl FormatNodeRule for FormatStmtTypeAlias { space(), token("="), space(), - maybe_parenthesize_expression(value, item, Parenthesize::IfBreaks) + FormatStatementsLastExpression::new(value, item) ] ) } diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__comments6.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__comments6.py.snap index f1bc3b617373d..5cb746cbf9698 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__comments6.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__comments6.py.snap @@ -130,18 +130,18 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite ```diff --- Black +++ Ruff -@@ -49,9 +49,7 @@ - element = 0 # type: int +@@ -50,8 +50,8 @@ another_element = 1 # type: float another_element_with_long_name = 2 # type: int -- another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = ( + another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = ( - 3 - ) # type: int -+ another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = 3 # type: int ++ 3 # type: int ++ ) an_element_with_a_long_value = calls() or more_calls() and more() # type: bool tup = ( -@@ -100,7 +98,13 @@ +@@ -100,7 +100,13 @@ ) c = call( @@ -156,7 +156,7 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite ) -@@ -108,11 +112,18 @@ +@@ -108,11 +114,18 @@ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ) @@ -233,7 +233,9 @@ def f( element = 0 # type: int another_element = 1 # type: float another_element_with_long_name = 2 # type: int - another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = 3 # type: int + another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = ( + 3 # type: int + ) an_element_with_a_long_value = calls() or more_calls() and more() # type: bool tup = ( diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__pep604_union_types_line_breaks.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__pep604_union_types_line_breaks.py.snap index 278a20e4a6650..b6349e7946e3d 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__pep604_union_types_line_breaks.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__pep604_union_types_line_breaks.py.snap @@ -95,7 +95,7 @@ def f( ```diff --- Black +++ Ruff -@@ -7,26 +7,16 @@ +@@ -7,26 +7,18 @@ ) # "AnnAssign"s now also work @@ -123,14 +123,16 @@ def f( -z: Short | Short2 | Short3 | Short4 = 8 -z: int = 2.3 -z: int = foo() -+z: Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong = 7 ++z: Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong = ( ++ 7 ++) +z: (Short | Short2 | Short3 | Short4) = 8 +z: (int) = 2.3 +z: (int) = foo() # In case I go for not enforcing parantheses, this might get improved at the same time x = ( -@@ -63,7 +53,7 @@ +@@ -63,7 +55,7 @@ # remove unnecessary paren @@ -139,7 +141,7 @@ def f( # this is a syntax error in the type annotation according to mypy, but it's not invalid *python* code, so make sure we don't mess with it and make it so. -@@ -72,12 +62,10 @@ +@@ -72,12 +64,10 @@ def foo( i: int, @@ -156,7 +158,7 @@ def f( *, s: str, ) -> None: -@@ -88,7 +76,7 @@ +@@ -88,7 +78,7 @@ async def foo( q: str | None = Query( None, title="Some long title", description="Some long description" @@ -185,7 +187,9 @@ z: (int) z: (int) -z: Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong = 7 +z: Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong | Loooooooooooooooooooooooong = ( + 7 +) z: (Short | Short2 | Short3 | Short4) = 8 z: (int) = 2.3 z: (int) = foo() diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__preview_cantfit.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__preview_cantfit.py.snap index c22c4b6ea4a72..f85533b8c99ae 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__preview_cantfit.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__preview_cantfit.py.snap @@ -51,29 +51,23 @@ del concatenated_strings, string_variable_name, normal_function_name, normal_nam ```diff --- Black +++ Ruff -@@ -1,18 +1,12 @@ - # long variable name --this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( -- 0 --) --this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( -- 1 # with a comment --) -+this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = 0 -+this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = 1 # with a comment - this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = [ - 1, - 2, - 3, - ] --this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( -- function() --) -+this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function() - this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function( - arg1, arg2, arg3 +@@ -13,11 +13,11 @@ + this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( + function() ) -@@ -35,10 +29,8 @@ +-this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function( +- arg1, arg2, arg3 ++this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( ++ function(arg1, arg2, arg3) + ) +-this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function( +- [1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3 ++this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( ++ function([1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3) + ) + # long function name + normal_name = ( +@@ -35,10 +35,8 @@ ) # long arguments normal_name = normal_function_name( @@ -92,19 +86,25 @@ del concatenated_strings, string_variable_name, normal_function_name, normal_nam ```python # long variable name -this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = 0 -this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = 1 # with a comment +this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( + 0 +) +this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( + 1 # with a comment +) this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = [ 1, 2, 3, ] -this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function() -this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function( - arg1, arg2, arg3 +this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( + function() ) -this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = function( - [1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3 +this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( + function(arg1, arg2, arg3) +) +this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it = ( + function([1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3) ) # long function name normal_name = ( diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap index 1b35bce81b919..7a73879f9f5eb 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap @@ -290,7 +290,9 @@ def f(*args, **kwargs): pass -this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd = 1 +this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd = ( + 1 +) session = MagicMock() models = MagicMock() diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__yield.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__yield.py.snap index 0d591cc737f80..c88d29f4c0bcf 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__yield.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__yield.py.snap @@ -165,7 +165,9 @@ def foo(): yield (e) # Too many parentheses # comment - for ridiculouslylongelementnameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee in l: + for ridiculouslylongelementnameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee in ( + l + ): yield ridiculouslylongelementnameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee for x in l: # comment diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__type_alias.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__type_alias.py.snap index ccc44b8db950a..a413e0fd6aa77 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__type_alias.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__type_alias.py.snap @@ -22,10 +22,12 @@ type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[Aaaaaaaaaaaaaaaaaaaaaaaaaaaa] = int type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[Aaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbb] = int type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt # with comment # long value type X = Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt type X = Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | Ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +type XXXXXXXXXXXXX = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt # with comment # soft keyword as alias name type type = int @@ -115,7 +117,9 @@ type X[T: int, *Ts, **P] = (T, Ts, P) type X[T: (int, str), *Ts, **P] = (T, Ts, P) # long name -type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = int +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = ( + int +) type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[ A ] = int @@ -126,7 +130,12 @@ type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Aaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbb, ] = int -type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = ( + Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt +) +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = ( + Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt # with comment +) # long value type X = Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt @@ -135,6 +144,9 @@ type X = ( | Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | Ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ) +type XXXXXXXXXXXXX = ( + Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt # with comment +) # soft keyword as alias name type type = int