From 38ff1127cf4f62cd192263b2454209fa4736a4fe Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 7 Oct 2026 22:49:33 +0200 Subject: [PATCH] Preserve author-added empty lines between reflowed arguments in blink --- .../fixer/rules/array_list_item_newline.go | 2 +- .../rules/array_list_item_newline_test.go | 2 +- .../fixer/rules/method_argument_space.go | 28 ++++++------------- .../fixer/rules/method_argument_space_test.go | 4 +-- .../standalone_line_in_multiline_array.go | 2 +- ...standalone_line_plain_constructor_param.go | 2 +- .../standalone_line_promoted_property.go | 2 +- .../standalone_line_promoted_property_test.go | 7 +++++ .../rules/standalone_line_required_param.go | 2 +- 9 files changed, 23 insertions(+), 28 deletions(-) diff --git a/blink/internal/fixer/rules/array_list_item_newline.go b/blink/internal/fixer/rules/array_list_item_newline.go index 35f6e87623..8a770c255b 100644 --- a/blink/internal/fixer/rules/array_list_item_newline.go +++ b/blink/internal/fixer/rules/array_list_item_newline.go @@ -66,7 +66,7 @@ func (ArrayListItemNewline) Fix(s *tokens.Stream) bool { closeIdx++ changed = true } - if reflowParen(s, open, closeIdx, false) { + if reflowParen(s, open, closeIdx) { changed = true } } diff --git a/blink/internal/fixer/rules/array_list_item_newline_test.go b/blink/internal/fixer/rules/array_list_item_newline_test.go index f4fdc9b465..318814f3fd 100644 --- a/blink/internal/fixer/rules/array_list_item_newline_test.go +++ b/blink/internal/fixer/rules/array_list_item_newline_test.go @@ -57,7 +57,7 @@ func TestArrayListItemNewline(t *testing.T) { t.Fatal("already-multiline inner must not break the outer opener") } - // a blank line a user put between array items is preserved (unlike call args) + // a blank line a user put between array items is preserved if _, changed := apply(t, f, " 1,\n\n 'b' => 2,\n];"); changed { t.Fatal("blank line between array items must be preserved") } diff --git a/blink/internal/fixer/rules/method_argument_space.go b/blink/internal/fixer/rules/method_argument_space.go index 478e7a37bb..08313d7c97 100644 --- a/blink/internal/fixer/rules/method_argument_space.go +++ b/blink/internal/fixer/rules/method_argument_space.go @@ -279,7 +279,7 @@ func reflowSingleArgOrMultiline(s *tokens.Stream) bool { if ensureSingleLineForParen(s, open, closeIdx) { changed = true } - } else if reflowParen(s, open, closeIdx, true) { + } else if reflowParen(s, open, closeIdx) { changed = true } } @@ -409,7 +409,7 @@ func reflowMultilineArgs(s *tokens.Stream) bool { if sigNext(s, open) == closeIdx { continue // empty () } - if reflowParen(s, open, closeIdx, true) { + if reflowParen(s, open, closeIdx) { changed = true } } @@ -542,7 +542,7 @@ func placeAttributesInParen(s *tokens.Stream, open, closeIdx int, placement stri // reflowParen puts each top-level argument of the paren at open on its own line, // with "(" and ")" on their own lines, indented one level past the call. -func reflowParen(s *tokens.Stream, open, closeIdx int, collapseBlanks bool) bool { +func reflowParen(s *tokens.Stream, open, closeIdx int) bool { changed := false base := lineIndentBefore(s, open) argNL := "\n" + base + " " @@ -573,7 +573,7 @@ func reflowParen(s *tokens.Stream, open, closeIdx int, collapseBlanks bool) bool changed = true } for _, c := range slices.Backward(commas) { - if reflowAfterComma(s, c, base, collapseBlanks) { + if reflowAfterComma(s, c, base) { changed = true } } @@ -638,7 +638,7 @@ func reflowBreakAfterComments(s *tokens.Stream, open, closeIdx int, base string) // comment that sits on the comma's line ("arg, // note" or "arg, /* note */") // stays there and the break goes after the comment, matching php-cs-fixer; // otherwise the break goes right after the comma. -func reflowAfterComma(s *tokens.Stream, comma int, base string, collapseBlanks bool) bool { +func reflowAfterComma(s *tokens.Stream, comma int, base string) bool { n := comma + 1 ws := -1 if n < s.Len() && s.At(n).Kind == token.Whitespace && !hasNewline(s.At(n).Value) { @@ -663,7 +663,7 @@ func reflowAfterComma(s *tokens.Stream, comma int, base string, collapseBlanks b } return changed } - return editSlotAfter(s, comma, argNLAfterComma(s, comma, base, collapseBlanks)) + return editSlotAfter(s, comma, argNLAfterComma(s, comma, base)) } // argListIsMultiline reports whether the argument list is split at the top level @@ -756,24 +756,12 @@ func lineIndentBefore(s *tokens.Stream, idx int) string { // arguments is preserved (ECS keeps blank lines in a multiline argument list and // only normalizes the indentation), so a comma whose following whitespace holds a // blank line keeps that blank rather than collapsing to a single newline. -func argNLAfterComma(s *tokens.Stream, comma int, base string, collapseBlanks bool) string { - // an array literal keeps a blank line a user put between items; a call or - // declaration list collapses it, except before a comment that annotates the - // next argument, which php-cs-fixer keeps +func argNLAfterComma(s *tokens.Stream, comma int, base string) string { if comma+1 < s.Len() { ws := s.At(comma + 1) if ws.Kind == token.Whitespace { if newlines := strings.Count(ws.Value, "\n"); newlines >= 2 { - keep := !collapseBlanks - if collapseBlanks { - if nx := nextSignificantIndex(s, comma); nx >= 0 && - isComment(s.At(nx)) && !isAttributeComment(s.At(nx)) { - keep = true - } - } - if keep { - return strings.Repeat("\n", newlines) + base + " " - } + return strings.Repeat("\n", newlines) + base + " " } } } diff --git a/blink/internal/fixer/rules/method_argument_space_test.go b/blink/internal/fixer/rules/method_argument_space_test.go index e69d9dc502..3bb7a31720 100644 --- a/blink/internal/fixer/rules/method_argument_space_test.go +++ b/blink/internal/fixer/rules/method_argument_space_test.go @@ -22,8 +22,8 @@ func TestMethodArgumentSpace(t *testing.T) { {"multiline arg list becomes fully multiline", "