From 68a02146b493ec5f7c450b297ef83e69454e74e7 Mon Sep 17 00:00:00 2001 From: Kazuki Nishikawa Date: Sun, 1 Sep 2024 15:52:50 +0900 Subject: [PATCH 1/3] fix bug for constant pattern and unnamed rest args pattern ref: #325 --- lib/rufo/formatter.rb | 94 ++++++------ .../pattern_matching.rb.spec | 144 +++++++++++++++++- 2 files changed, 193 insertions(+), 45 deletions(-) diff --git a/lib/rufo/formatter.rb b/lib/rufo/formatter.rb index ccd24755..db3cf255 100644 --- a/lib/rufo/formatter.rb +++ b/lib/rufo/formatter.rb @@ -3084,46 +3084,75 @@ def visit_array_pattern(node) _, const_ref, pre_rest, rest, post_rest = node if const_ref - return visit_constant_pattern(node) + visit const_ref end + left_paren_token, right_paren_token = if current_token_kind == :on_lparen + %i[on_lparen on_rparen] + elsif current_token_kind == :on_lbracket + %i[on_lbracket on_rbracket] + else + [] + end + # pattern is [*] if !pre_rest && !post_rest && rest == [:var_field, nil] - consume_token :on_lbracket + if left_paren_token + consume_token left_paren_token + end + skip_space_or_newline consume_op "*" skip_space_or_newline - consume_token :on_rbracket + + if right_paren_token + consume_token right_paren_token + end return end token_column = current_token_column - has_bracket = current_token_kind == :on_lbracket - if has_bracket - consume_token :on_lbracket + if left_paren_token + consume_token left_paren_token skip_space end - write_comma = false + newline = newline? + wrote_comma = false if pre_rest - visit_literal_elements pre_rest, inside_array: true, token_column: token_column, keep_final_newline: !has_bracket - write_comma = true - end + visit_comma_separated_list pre_rest + skip_space - # pattern like `[a,]` will make `rest` as `[:var_field, nil]` - if rest && ((var_name_node = rest[1]) || current_token_value == "*") - if write_comma + if comma? + check :on_comma write "," - consume_space - else + next_token + skip_space + wrote_comma = true + end + if newline skip_space_or_newline + write_line + write_indent end + end - consume_op "*" - if var_name_node - visit rest + if rest + if wrote_comma + consume_space end + + # pattern like `[a,]` will make `rest` as `[:var_field, nil]` + if (var_name_node = rest[1]) || current_token_value == "*" + consume_op "*" + if var_name_node + visit rest + end + end + elsif wrote_comma && !newline? + # In Ruby 3.3, rest is nil when the code is like `[a,]`. Insert a space after comma at here. + consume_space end if post_rest @@ -3133,36 +3162,13 @@ def visit_array_pattern(node) consume_space next_token - visit_literal_elements post_rest, inside_array: true, token_column: token_column, keep_final_newline: !has_bracket + visit_literal_elements post_rest, inside_array: true, token_column: token_column, keep_final_newline: !left_paren_token end skip_space - if has_bracket - consume_token :on_rbracket - end - end - - def visit_constant_pattern(node) - # [:aryptn, const_ref, args] - _, const_ref, args = node - visit const_ref - - parens = current_token_kind == :on_lparen - if parens - consume_token :on_lparen - else - consume_token :on_lbracket - end - - skip_space - visit_comma_separated_list args - - skip_space - if parens - consume_token :on_rparen - else - consume_token :on_rbracket + if right_paren_token + consume_token right_paren_token end end diff --git a/spec/lib/rufo/formatter_source_specs/pattern_matching.rb.spec b/spec/lib/rufo/formatter_source_specs/pattern_matching.rb.spec index f0169bc2..b2ded974 100644 --- a/spec/lib/rufo/formatter_source_specs/pattern_matching.rb.spec +++ b/spec/lib/rufo/formatter_source_specs/pattern_matching.rb.spec @@ -73,7 +73,7 @@ end #~# ORIGINAL alternative pattern case a - in String | [1, * ] + in String | [1 , * ] puts x else puts "2" @@ -199,6 +199,36 @@ in [ a end +#~# ORIGINAL +case [0] + in [ + a, b, + c + ] + a +end + +#~# EXPECTED +case [0] +in [ + a, b, + c + ] + a +end + +#~# ORIGINAL +case [0] + in [ a , ] + a +end + +#~# EXPECTED +case [0] +in [a, ] + a +end + #~# ORIGINAL array pattern (newline after comma) case [0] in [ a, @@ -796,3 +826,115 @@ case x in { "a": 1 } 1 end + +#~# ORIGINAL issue_325 +case "baz" + in Foo[*data] # This splat is what causes the crash + puts "foo" + else + puts "bar" +end + +#~# EXPECTED +case "baz" +in Foo[*data] # This splat is what causes the crash + puts "foo" +else + puts "bar" +end + +#~# ORIGINAL +case x + in Foo[a, ] + 1 +end + +#~# EXPECTED +case x +in Foo[a, ] + 1 +end + +#~# ORIGINAL +case x + in Foo[ a, * ] + 1 +end + +#~# EXPECTED +case x +in Foo[a, *] + 1 +end + +#~# ORIGINAL +case x + in Foo[ a, *b ] + 1 +end + +#~# EXPECTED +case x +in Foo[a, *b] + 1 +end + +#~# ORIGINAL +case x + in Foo[ *a,b,*c ] + 1 +end + +#~# EXPECTED +case x +in Foo[*a, b, *c] + 1 +end + +#~# ORIGINAL +case x + in Foo[ *,a,* ] + 1 +end + +#~# EXPECTED +case x +in Foo[*, a, *] + 1 +end + +#~# ORIGINAL +case x + in Foo[ a,*b,c ] + 1 +end + +#~# EXPECTED +case x +in Foo[a, *b, c] + 1 +end + +#~# ORIGINAL +case x + in Foo[ * ] + 1 +end + +#~# EXPECTED +case x +in Foo[*] + 1 +end + +#~# ORIGINAL +case x + in Foo( *) + 1 +end + +#~# EXPECTED +case x +in Foo(*) + 1 +end From 914982eb241dcdbbf8a15ff6938de377bd0d60e5 Mon Sep 17 00:00:00 2001 From: Kazuki Nishikawa Date: Sun, 1 Sep 2024 16:24:08 +0900 Subject: [PATCH 2/3] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 618e9a83..846beda1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Fixed +- Fix error when formatting pattern matching syntax ([#325](https://github.com/ruby-formatter/rufo/pull/325)) ### Changed From 2a6abedb504b2ae795a86933fc4274f26d7d62fe Mon Sep 17 00:00:00 2001 From: Kazuki Nishikawa Date: Sun, 1 Sep 2024 17:28:23 +0900 Subject: [PATCH 3/3] run rufo --- lib/rufo/formatter.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/rufo/formatter.rb b/lib/rufo/formatter.rb index db3cf255..b4a7f614 100644 --- a/lib/rufo/formatter.rb +++ b/lib/rufo/formatter.rb @@ -3088,12 +3088,12 @@ def visit_array_pattern(node) end left_paren_token, right_paren_token = if current_token_kind == :on_lparen - %i[on_lparen on_rparen] - elsif current_token_kind == :on_lbracket - %i[on_lbracket on_rbracket] - else - [] - end + %i[on_lparen on_rparen] + elsif current_token_kind == :on_lbracket + %i[on_lbracket on_rbracket] + else + [] + end # pattern is [*] if !pre_rest && !post_rest && rest == [:var_field, nil] @@ -3142,7 +3142,7 @@ def visit_array_pattern(node) if wrote_comma consume_space end - + # pattern like `[a,]` will make `rest` as `[:var_field, nil]` if (var_name_node = rest[1]) || current_token_value == "*" consume_op "*"