From d013b71974fe65b4afa2b93c212d712e353201e5 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Fri, 1 Dec 2023 11:51:37 +0800 Subject: [PATCH] Ignore the open parentheses when measuring `BestFitsParenthesize` --- crates/ruff_formatter/src/builders.rs | 9 +-- crates/ruff_formatter/src/printer/mod.rs | 11 ++-- ...ack_compatibility@cases__comments6.py.snap | 16 ++--- ...es__pep604_union_types_line_breaks.py.snap | 16 +++-- ...mpatibility@cases__preview_cantfit.py.snap | 58 +++++++++---------- .../snapshots/format@expression__call.py.snap | 4 +- .../format@expression__yield.py.snap | 4 +- .../format@statement__type_alias.py.snap | 8 ++- 8 files changed, 72 insertions(+), 54 deletions(-) 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/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 6320591b80c05..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 @@ -117,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 @@ -128,7 +130,9 @@ type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Aaaaaaaaaaaaaaaaaaaaaaaaaaaa, Bbbbbbbbbbbbb, ] = int -type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt +type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = ( + Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt +) type Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = ( Tttttttttttttttttttttttttttttttttttttttttttttttttttttttt # with comment )