diff --git a/CHANGELOG.md b/CHANGELOG.md index ccc8726c9..a05893e0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,9 @@ by taking precedence over SPLIT_BEFORE_NAMED_ASSIGNS. - Fix SPLIT_ALL_COMMA_SEPARATED_VALUES and SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES being too agressive for lambdas and unpacking. +- Fix a short, no-argument function call in a list being forced onto its own + line just because the list as a whole didn't fit on one line, producing + inconsistent formatting between call and non-call elements. ## [0.40.2] 2023-09-22 ### Changes diff --git a/yapf/yapflib/format_decision_state.py b/yapf/yapflib/format_decision_state.py index 06f3455d9..8c31321fc 100644 --- a/yapf/yapflib/format_decision_state.py +++ b/yapf/yapflib/format_decision_state.py @@ -317,11 +317,18 @@ def SurroundedByParens(token): if func_call_or_string_format: open_bracket = logical_line.IsSurroundedByBrackets(current) if open_bracket: - if open_bracket.value in '[{': + if open_bracket.value in '[{' and tok.value != '(': if not self._FitsOnLine(open_bracket, open_bracket.matching_bracket): return True elif tok.value == '(': + # Only force a split before this function-call element if the + # call itself doesn't fit on the line. Checking whether the + # *whole* surrounding list/dict fits (as above) forces a split + # before every function-call element whenever the container is + # too long overall, even for short calls like `f()`, producing + # inconsistent formatting between call and non-call elements. + # See https://github.com/google/yapf/issues/422. if not self._FitsOnLine(current, tok.matching_bracket): return True diff --git a/yapftests/reformatter_basic_test.py b/yapftests/reformatter_basic_test.py index 74b1ba405..f772189c8 100644 --- a/yapftests/reformatter_basic_test.py +++ b/yapftests/reformatter_basic_test.py @@ -2816,6 +2816,22 @@ def foo(): llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) self.assertCodeEqual(expected_code, reformatter.Reformat(llines)) + def testListWithShortFunctionCallsAmongPlainElements(self): + # A short, no-argument function call in a list shouldn't be forced onto + # its own line just because the list as a whole doesn't fit: only calls + # that don't themselves fit on the line should be split like that. + # See https://github.com/google/yapf/issues/422. + unformatted_code = textwrap.dedent("""\ + array = [first, make_second(), third, fourth, fifth, make_sixth(), seventh, eighth] + """) + expected_code = textwrap.dedent("""\ + array = [ + first, make_second(), third, fourth, fifth, make_sixth(), seventh, eighth + ] + """) + llines = yapf_test_helper.ParseAndUnwrap(unformatted_code) + self.assertCodeEqual(expected_code, reformatter.Reformat(llines)) + def testEllipses(self): unformatted_code = textwrap.dedent("""\ X=...