rufo 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1862ef1cb223254a0b735f6af30b3364045bd1c8673ad2c34ccd381571174377
4
- data.tar.gz: 38d6908494f4a93cc527e914281e44c329dbec4b82a3ca4873acbf188856a559
3
+ metadata.gz: 52f19e023f290af007e285561a6806deec68912a07640c70221493f73f8f80a8
4
+ data.tar.gz: 118543384b66bdad4066b710b40f922c192833809a64e6a1075622fa3c1e80a8
5
5
  SHA512:
6
- metadata.gz: c8d78360444224de4502c9f727171e7df9e4ff3344e48b28475d0cf9d92f53d6807755542db05c99d3eaa54cde3f6c2cbe5b67c7b1583d3d5e4346b4c93c7afa
7
- data.tar.gz: f62ce1f77275410744f235c74a2293d838a5dfe6110768f6434735cc935e7520d6bc0511496e9d5c5912a945a783ac989c990a8bc8b7f61bfffb05c7055f7008
6
+ metadata.gz: f03e8e965486ce6f0920c3a9ef1fc9d3d3574c7fe75f64e04da03023be985d2677c4b0560044422f216857a1e9b87e0155c13d0f390dabb0f4354c7f941f32e1
7
+ data.tar.gz: 83ac8d4527b5c72260d56d827c681dded32a38e31763dc1c0b11b17d3549e19d476d0aa07345d13ea9c262a595a6010af39c69ac62fbd98d7f4507381f6ad5dd
data/.gitignore CHANGED
@@ -17,3 +17,4 @@ spec/examples.txt
17
17
  sample_code
18
18
 
19
19
  .byebug_history
20
+ .dir-locals.el
data/CHANGELOG.md CHANGED
@@ -12,6 +12,28 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
12
12
 
13
13
  ### Added
14
14
 
15
+ ## [0.16.0] - 2023-04-02
16
+
17
+ ### Fixed
18
+
19
+ - Formats ERB files with configuration (issue [275](https://github.com/ruby-formatter/rufo/issues/275))
20
+
21
+ ### Changed
22
+
23
+ ### Added
24
+
25
+ - Support for pattern matching syntax
26
+
27
+ ## [0.15.1] - 2023-02-08
28
+
29
+ ### Fixed
30
+
31
+ - Fix Bug: raises error while formatting anonymous block argument forwarding
32
+
33
+ ### Changed
34
+
35
+ ### Added
36
+
15
37
  ## [0.15.0] - 2023-02-08
16
38
 
17
39
  ### Fixed
data/bin/runtest ADDED
@@ -0,0 +1,10 @@
1
+ #!/bin/sh
2
+
3
+ for ver in "2.7.6" "3.0.4" "3.1.3" "3.2.0"; do
4
+ rbenv local "$ver"
5
+ (bundle check || bundle) && rake
6
+ if [ $? != 0 ]; then
7
+ echo "failed on $ver"
8
+ exit 1
9
+ fi
10
+ done
@@ -159,7 +159,7 @@ class Rufo::ErbFormatter
159
159
  end
160
160
 
161
161
  def format_code(str)
162
- Rufo::Formatter.format(str).chomp
162
+ Rufo::Formatter.format(str, **@options).chomp
163
163
  end
164
164
 
165
165
  def enable_code_mode
@@ -227,7 +227,7 @@ class Rufo::Formatter
227
227
  when :@CHAR
228
228
  # [:@CHAR, "?a", [1, 0]]
229
229
  consume_token :on_CHAR
230
- when :@gvar, :@backref, :@label, :@op
230
+ when :@backref, :@label, :@op
231
231
  # [:@gvar, "$abc", [1, 0]]
232
232
  # [:@backref, "$1", [1, 0]]
233
233
  # [:@label, "foo:", [1, 3]]
@@ -287,6 +287,7 @@ class Rufo::Formatter
287
287
  when :dyna_symbol
288
288
  visit_quoted_symbol_literal(node)
289
289
  when :@ident
290
+ consume_pin_op
290
291
  consume_token :on_ident
291
292
  when :var_ref, :var_field, :const_ref, :vcall, :fcall
292
293
  # [:var_ref, exp]
@@ -300,10 +301,16 @@ class Rufo::Formatter
300
301
  consume_token :on_kw
301
302
  when :@ivar
302
303
  # [:@ivar, "@foo", [1, 0]]
304
+ consume_pin_op
303
305
  consume_token :on_ivar
304
306
  when :@cvar
305
307
  # [:@cvar, "@@foo", [1, 0]]
308
+ consume_pin_op
306
309
  consume_token :on_cvar
310
+ when :@gvar
311
+ # [:@gvar, "$foo", [1, 0]]
312
+ consume_pin_op
313
+ consume_token :on_gvar
307
314
  when :@const
308
315
  # [:@const, "FOO", [1, 0]]
309
316
  consume_token :on_const
@@ -377,7 +384,7 @@ class Rufo::Formatter
377
384
  visit_until(node)
378
385
  when :case
379
386
  visit_case(node)
380
- when :when
387
+ when :when, :in
381
388
  visit_when(node)
382
389
  when :unary
383
390
  visit_unary(node)
@@ -470,6 +477,12 @@ class Rufo::Formatter
470
477
  visit_end_node(node)
471
478
  when :args_forward
472
479
  consume_op("...")
480
+ when :aryptn
481
+ visit_array_pattern(node)
482
+ when :fndptn
483
+ visit_find_pattern(node)
484
+ when :hshptn
485
+ visit_hash_pattern(node)
473
486
  else
474
487
  bug "Unhandled node: #{node.first}"
475
488
  end
@@ -1485,7 +1498,11 @@ class Rufo::Formatter
1485
1498
  visit_comma_separated_list args
1486
1499
  end
1487
1500
 
1488
- if block_arg
1501
+ # block_arg will be...
1502
+ # - named => node
1503
+ # - anonymous => nil
1504
+ # - no arg => false
1505
+ if block_arg || block_arg.nil?
1489
1506
  skip_space_or_newline
1490
1507
 
1491
1508
  if comma?
@@ -1496,10 +1513,9 @@ class Rufo::Formatter
1496
1513
 
1497
1514
  consume_op "&"
1498
1515
  skip_space_or_newline
1499
- visit block_arg
1500
- elsif current_token_kind == :on_op && current_token_value == "&"
1501
- consume_op "&"
1502
- skip_space_or_newline
1516
+ if block_arg
1517
+ visit block_arg
1518
+ end
1503
1519
  end
1504
1520
  end
1505
1521
 
@@ -1540,13 +1556,26 @@ class Rufo::Formatter
1540
1556
  end
1541
1557
 
1542
1558
  def visit_begin(node)
1543
- # begin
1544
- # body
1545
- # end
1546
- #
1547
- # [:begin, [:bodystmt, body, rescue_body, else_body, ensure_body]]
1548
- consume_keyword "begin"
1549
- visit node[1]
1559
+ if op?("^")
1560
+ # ^(expression)
1561
+ #
1562
+ # [:begin, expression_node]
1563
+ consume_op "^"
1564
+ skip_space
1565
+ consume_token :on_lparen
1566
+ skip_space
1567
+ visit node[1]
1568
+ skip_space
1569
+ consume_token :on_rparen
1570
+ else
1571
+ # begin
1572
+ # body
1573
+ # end
1574
+ #
1575
+ # [:begin, [:bodystmt, body, rescue_body, else_body, ensure_body]]
1576
+ consume_keyword "begin"
1577
+ visit node[1]
1578
+ end
1550
1579
  end
1551
1580
 
1552
1581
  def visit_bodystmt(node)
@@ -1797,7 +1826,7 @@ class Rufo::Formatter
1797
1826
  # Maybe a Ripper bug, but if there's something before a star
1798
1827
  # then a star shouldn't be here... but if it is... handle it
1799
1828
  # somehow...
1800
- if current_token_kind == :on_op && current_token_value == "*"
1829
+ if op?("*")
1801
1830
  star = before
1802
1831
  else
1803
1832
  visit_comma_separated_list to_ary(before)
@@ -2350,7 +2379,7 @@ class Rufo::Formatter
2350
2379
  token_column = current_token_column
2351
2380
 
2352
2381
  closing_brace_token, _ = find_closing_brace_token
2353
- need_space = need_space_for_hash?(node, closing_brace_token)
2382
+ need_space = need_space_for_hash?(node, node[1], closing_brace_token)
2354
2383
 
2355
2384
  check :on_lbrace
2356
2385
  write "{"
@@ -2730,7 +2759,7 @@ class Rufo::Formatter
2730
2759
  visit_comma_separated_list exps
2731
2760
  end
2732
2761
 
2733
- def visit_literal_elements(elements, inside_hash: false, inside_array: false, token_column:)
2762
+ def visit_literal_elements(elements, inside_hash: false, inside_array: false, token_column:, keep_final_newline: false, &block)
2734
2763
  base_column = @column
2735
2764
  base_line = @line
2736
2765
  needs_final_space = (inside_hash || inside_array) && space?
@@ -2767,6 +2796,7 @@ class Rufo::Formatter
2767
2796
  wrote_comma = false
2768
2797
  first_space = nil
2769
2798
 
2799
+ visitor = block_given? ? block : ->(elem) { visit elem }
2770
2800
  elements.each_with_index do |elem, i|
2771
2801
  @literal_elements_level = @node_level
2772
2802
 
@@ -2774,9 +2804,9 @@ class Rufo::Formatter
2774
2804
  wrote_comma = false
2775
2805
 
2776
2806
  if needs_trailing_comma
2777
- indent(needed_indent) { visit elem }
2807
+ indent(needed_indent) { visitor.call(elem) }
2778
2808
  else
2779
- visit elem
2809
+ visitor.call(elem)
2780
2810
  end
2781
2811
 
2782
2812
  # We have to be careful not to aumatically write a heredoc on next_token,
@@ -2826,6 +2856,8 @@ class Rufo::Formatter
2826
2856
  else
2827
2857
  if needs_final_space
2828
2858
  consume_space
2859
+ elsif keep_final_newline
2860
+ skip_space
2829
2861
  else
2830
2862
  skip_space_or_newline
2831
2863
  end
@@ -2935,31 +2967,55 @@ class Rufo::Formatter
2935
2967
  # [:case, cond, case_when]
2936
2968
  _, cond, case_when = node
2937
2969
 
2938
- consume_keyword "case"
2970
+ # If node is inline pattern matching, case_expression will be false
2971
+ case_expression = keyword?("case")
2972
+ if case_expression
2973
+ consume_keyword "case"
2974
+ end
2939
2975
 
2940
2976
  if cond
2941
2977
  consume_space
2942
2978
  visit cond
2943
2979
  end
2944
2980
 
2945
- consume_end_of_line
2946
-
2947
- write_indent
2981
+ if case_expression
2982
+ consume_end_of_line
2983
+ write_indent
2984
+ else
2985
+ consume_space
2986
+ end
2948
2987
  visit case_when
2949
2988
 
2950
- write_indent
2951
- consume_keyword "end"
2989
+ if case_expression
2990
+ write_indent
2991
+ consume_keyword "end"
2992
+ end
2952
2993
  end
2953
2994
 
2954
2995
  def visit_when(node)
2955
2996
  # [:when, conds, body, next_exp]
2956
- _, conds, body, next_exp = node
2997
+ # [:in, pattern, body, next_exp]
2998
+ kw, conds_or_pattern, body, next_exp = node
2957
2999
 
2958
- consume_keyword "when"
3000
+ case kw
3001
+ when :when
3002
+ consume_keyword "when"
3003
+ when :in
3004
+ if current_token_kind == :on_op
3005
+ consume_op "=>"
3006
+ else
3007
+ consume_keyword "in"
3008
+ end
3009
+ end
2959
3010
  consume_space
2960
3011
 
2961
3012
  indent(@column) do
2962
- visit_comma_separated_list conds
3013
+ case kw
3014
+ when :when
3015
+ visit_comma_separated_list conds_or_pattern
3016
+ when :in
3017
+ visit conds_or_pattern
3018
+ end
2963
3019
  skip_space
2964
3020
  end
2965
3021
  written_space = false
@@ -3017,12 +3073,15 @@ class Rufo::Formatter
3017
3073
  end
3018
3074
  end
3019
3075
 
3020
- if inline
3021
- indent do
3022
- visit_exps body
3076
+ # If node is inline pattern matching, body will be nil
3077
+ if body
3078
+ if inline
3079
+ indent do
3080
+ visit_exps body
3081
+ end
3082
+ else
3083
+ indent_body body
3023
3084
  end
3024
- else
3025
- indent_body body
3026
3085
  end
3027
3086
 
3028
3087
  if next_exp
@@ -3053,6 +3112,232 @@ class Rufo::Formatter
3053
3112
  end
3054
3113
  end
3055
3114
 
3115
+ def visit_array_pattern(node)
3116
+ # [:aryptn, const_ref, pre_rest, rest, post_rest]
3117
+ _, const_ref, pre_rest, rest, post_rest = node
3118
+
3119
+ if const_ref
3120
+ return visit_constant_pattern(node)
3121
+ end
3122
+
3123
+ # pattern is [*]
3124
+ if !pre_rest && !post_rest && rest == [:var_field, nil]
3125
+ consume_token :on_lbracket
3126
+ skip_space_or_newline
3127
+ consume_op "*"
3128
+ skip_space_or_newline
3129
+ consume_token :on_rbracket
3130
+ return
3131
+ end
3132
+
3133
+ token_column = current_token_column
3134
+
3135
+ has_bracket = current_token_kind == :on_lbracket
3136
+ if has_bracket
3137
+ consume_token :on_lbracket
3138
+ skip_space
3139
+ end
3140
+
3141
+ write_comma = false
3142
+ if pre_rest
3143
+ visit_literal_elements pre_rest, inside_array: true, token_column: token_column, keep_final_newline: !has_bracket
3144
+ write_comma = true
3145
+ end
3146
+
3147
+ # pattern like `[a,]` will make `rest` as `[:var_field, nil]`
3148
+ if rest && ((var_name_node = rest[1]) || current_token_value == "*")
3149
+ if write_comma
3150
+ write ","
3151
+ consume_space
3152
+ else
3153
+ skip_space_or_newline
3154
+ end
3155
+
3156
+ consume_op "*"
3157
+ if var_name_node
3158
+ visit rest
3159
+ end
3160
+ end
3161
+
3162
+ if post_rest
3163
+ skip_space
3164
+ check :on_comma
3165
+ write ","
3166
+ consume_space
3167
+ next_token
3168
+
3169
+ visit_literal_elements post_rest, inside_array: true, token_column: token_column, keep_final_newline: !has_bracket
3170
+ end
3171
+
3172
+ skip_space
3173
+ if has_bracket
3174
+ consume_token :on_rbracket
3175
+ end
3176
+ end
3177
+
3178
+ def visit_constant_pattern(node)
3179
+ # [:aryptn, const_ref, args]
3180
+ _, const_ref, args = node
3181
+
3182
+ visit const_ref
3183
+
3184
+ parens = current_token_kind == :on_lparen
3185
+ if parens
3186
+ consume_token :on_lparen
3187
+ else
3188
+ consume_token :on_lbracket
3189
+ end
3190
+
3191
+ skip_space
3192
+ visit_comma_separated_list args
3193
+
3194
+ skip_space
3195
+ if parens
3196
+ consume_token :on_rparen
3197
+ else
3198
+ consume_token :on_rbracket
3199
+ end
3200
+ end
3201
+
3202
+ def visit_find_pattern(node)
3203
+ # [:fndptn, const_ref, pre, patterns, post]
3204
+ _, const_ref, pre, patterns, post = node
3205
+
3206
+ parens = if const_ref
3207
+ visit const_ref
3208
+ current_token_kind == :on_lparen
3209
+ else
3210
+ false
3211
+ end
3212
+
3213
+ if parens
3214
+ consume_token :on_lparen
3215
+ else
3216
+ consume_token :on_lbracket
3217
+ end
3218
+
3219
+ skip_space
3220
+ consume_op "*"
3221
+ if pre[1] # check pre has name or not
3222
+ visit pre
3223
+ end
3224
+
3225
+ patterns.each do |pattern|
3226
+ skip_space
3227
+ consume_token :on_comma
3228
+ consume_space
3229
+ visit pattern
3230
+ end
3231
+
3232
+ skip_space
3233
+ consume_token :on_comma
3234
+ consume_space
3235
+ consume_op "*"
3236
+ if post[1] # check post has name or not
3237
+ visit post
3238
+ end
3239
+
3240
+ skip_space
3241
+ if parens
3242
+ consume_token :on_rparen
3243
+ else
3244
+ consume_token :on_rbracket
3245
+ end
3246
+ end
3247
+
3248
+ def visit_hash_pattern(node)
3249
+ _, const_ref, elements, rest = node
3250
+
3251
+ if const_ref
3252
+ visit const_ref
3253
+ end
3254
+
3255
+ token_column = current_token_column
3256
+
3257
+ need_space = false
3258
+ expected_right_token = nil
3259
+ if const_ref
3260
+ if current_token_kind == :on_lparen
3261
+ consume_token :on_lparen
3262
+ expected_right_token = :on_rparen
3263
+ else
3264
+ consume_token :on_lbracket
3265
+ expected_right_token = :on_rbracket
3266
+ end
3267
+ elsif current_token_kind == :on_lbrace
3268
+ expected_right_token = :on_rbrace
3269
+ closing_brace_token, _ = find_closing_brace_token
3270
+ need_space = need_space_for_hash?(node, [*elements, rest].compact, closing_brace_token)
3271
+
3272
+ consume_token :on_lbrace
3273
+ brace_position = @output.length - 1
3274
+ consume_space if need_space
3275
+ end
3276
+
3277
+ # pattern is {}
3278
+ empty = !const_ref && !elements && !rest
3279
+ if empty
3280
+ consume_token :on_rbrace
3281
+ return
3282
+ end
3283
+
3284
+ # pattern is {**}
3285
+ empty = !const_ref && elements.empty? && !rest
3286
+ if empty
3287
+ consume_space
3288
+ consume_op "**"
3289
+ consume_space
3290
+ consume_token :on_rbrace
3291
+ return
3292
+ end
3293
+
3294
+ visit_literal_elements elements, inside_hash: true, token_column: token_column, keep_final_newline: expected_right_token.nil? do |element|
3295
+ key, value = element
3296
+ visit key
3297
+ if value
3298
+ consume_space
3299
+ visit value
3300
+ end
3301
+ end
3302
+
3303
+ if rest || op?("**") || comma?
3304
+ unless elements.empty?
3305
+ write ","
3306
+ end
3307
+
3308
+ skip_space_or_newline
3309
+ if rest || op?("**")
3310
+ consume_space
3311
+ consume_op "**"
3312
+ if rest
3313
+ visit rest
3314
+ end
3315
+ end
3316
+ end
3317
+
3318
+ unless expected_right_token.nil?
3319
+ skip_space
3320
+
3321
+ if expected_right_token == :on_rbrace
3322
+ # in some case, need_space_for_hash? might be unexpected behaviour for some patterns, example:
3323
+ # { a: 1,
3324
+ # ** }
3325
+ # so re-check need_space? at here, and insert a space in the missing position if needed.
3326
+ char_after_brace = @output[brace_position + 1]
3327
+ if !need_space && !["\n", " "].include?(char_after_brace)
3328
+ need_space = true
3329
+ @output.insert(brace_position + 1, " ")
3330
+ end
3331
+ end
3332
+
3333
+ check expected_right_token
3334
+ right = current_token_value
3335
+ write " " if need_space
3336
+ write right
3337
+ next_token
3338
+ end
3339
+ end
3340
+
3056
3341
  def consume_space(want_preserve_whitespace: false)
3057
3342
  first_space = skip_space
3058
3343
  if want_preserve_whitespace && !newline? && !comment? && first_space
@@ -3404,6 +3689,13 @@ class Rufo::Formatter
3404
3689
  end
3405
3690
  end
3406
3691
 
3692
+ def consume_pin_op
3693
+ return unless op?("^")
3694
+
3695
+ consume_op "^"
3696
+ skip_space
3697
+ end
3698
+
3407
3699
  def indent(value = nil)
3408
3700
  if value
3409
3701
  old_indent = @indent
@@ -3653,6 +3945,10 @@ class Rufo::Formatter
3653
3945
  current_token_kind == :on_sp
3654
3946
  end
3655
3947
 
3948
+ def op?(value)
3949
+ current_token_kind == :on_op && current_token_value == value
3950
+ end
3951
+
3656
3952
  def void_exps?(node)
3657
3953
  node.size == 1 && node[0].size == 1 && node[0][0] == :void_stmt
3658
3954
  end
@@ -3884,8 +4180,8 @@ class Rufo::Formatter
3884
4180
  end
3885
4181
 
3886
4182
  # Check to see if need to add space inside hash literal braces.
3887
- def need_space_for_hash?(node, closing_brace_token)
3888
- return false unless node[1]
4183
+ def need_space_for_hash?(node, elements, closing_brace_token)
4184
+ return false if elements.nil? || elements.empty?
3889
4185
 
3890
4186
  left_need_space = current_token_line == node_line(node, beginning: true)
3891
4187
  right_need_space = closing_brace_token[0][0] == node_line(node, beginning: false)
@@ -3898,8 +4194,16 @@ class Rufo::Formatter
3898
4194
  # get line of node, it is only used in visit_hash right now,
3899
4195
  # so handling the following node types is enough.
3900
4196
  case node.first
3901
- when :hash, :string_literal, :symbol_literal, :symbol, :vcall, :string_content, :assoc_splat, :var_ref, :dyna_symbol
4197
+ when :hash, :string_literal, :symbol_literal, :symbol, :vcall, :string_content, :assoc_splat, :var_ref, :dyna_symbol, :var_field
3902
4198
  node_line(node[1], beginning: beginning)
4199
+ when :hshptn
4200
+ _, _, elements, rest = node
4201
+ elem = if beginning
4202
+ (elements[0] && elements[0][0]) || rest
4203
+ else
4204
+ rest || elements.last[0]
4205
+ end
4206
+ node_line(elem, beginning: beginning)
3903
4207
  when :assoc_new
3904
4208
  # There's no line number info for empty strings or hashes.
3905
4209
  if node[1] != EMPTY_STRING && node[1] != EMPTY_HASH
data/lib/rufo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rufo
4
- VERSION = "0.15.0"
4
+ VERSION = "0.16.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ary Borenszweig
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-02-08 00:00:00.000000000 Z
11
+ date: 2023-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -171,6 +171,7 @@ files:
171
171
  - README.md
172
172
  - Rakefile
173
173
  - bin/console
174
+ - bin/runtest
174
175
  - bin/setup
175
176
  - bin/verify-sample-code
176
177
  - docs/developing-rufo.md