rufo 0.15.1 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd22e372dba08b9779d73ceafaae522433e848e1283ef487baf5e366aaa58986
4
- data.tar.gz: 8729947df2863f8f36ad539879750dd53c9f33c0c2885c2985984e0d07862ddc
3
+ metadata.gz: 52f19e023f290af007e285561a6806deec68912a07640c70221493f73f8f80a8
4
+ data.tar.gz: 118543384b66bdad4066b710b40f922c192833809a64e6a1075622fa3c1e80a8
5
5
  SHA512:
6
- metadata.gz: 45f6c8259e2c20db8cd2e53778d0d8b7d3cfd57686eff05c650b61073338c9d5e89f3ed2e29a35f2e867a1b0a4ae50a7e205ce611b863b215751ffaf2522890a
7
- data.tar.gz: 7d1d00b02060d5b4dcf01e91c1ee41cb955917b1bac5fd149f3e1d217e95aeeeb3e25920c321bed22b5635c2168d1d962fa2b0149efa68138680d45229121632
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,18 @@ 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
+
15
27
  ## [0.15.1] - 2023-02-08
16
28
 
17
29
  ### 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
@@ -1543,13 +1556,26 @@ class Rufo::Formatter
1543
1556
  end
1544
1557
 
1545
1558
  def visit_begin(node)
1546
- # begin
1547
- # body
1548
- # end
1549
- #
1550
- # [:begin, [:bodystmt, body, rescue_body, else_body, ensure_body]]
1551
- consume_keyword "begin"
1552
- 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
1553
1579
  end
1554
1580
 
1555
1581
  def visit_bodystmt(node)
@@ -1800,7 +1826,7 @@ class Rufo::Formatter
1800
1826
  # Maybe a Ripper bug, but if there's something before a star
1801
1827
  # then a star shouldn't be here... but if it is... handle it
1802
1828
  # somehow...
1803
- if current_token_kind == :on_op && current_token_value == "*"
1829
+ if op?("*")
1804
1830
  star = before
1805
1831
  else
1806
1832
  visit_comma_separated_list to_ary(before)
@@ -2353,7 +2379,7 @@ class Rufo::Formatter
2353
2379
  token_column = current_token_column
2354
2380
 
2355
2381
  closing_brace_token, _ = find_closing_brace_token
2356
- need_space = need_space_for_hash?(node, closing_brace_token)
2382
+ need_space = need_space_for_hash?(node, node[1], closing_brace_token)
2357
2383
 
2358
2384
  check :on_lbrace
2359
2385
  write "{"
@@ -2733,7 +2759,7 @@ class Rufo::Formatter
2733
2759
  visit_comma_separated_list exps
2734
2760
  end
2735
2761
 
2736
- 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)
2737
2763
  base_column = @column
2738
2764
  base_line = @line
2739
2765
  needs_final_space = (inside_hash || inside_array) && space?
@@ -2770,6 +2796,7 @@ class Rufo::Formatter
2770
2796
  wrote_comma = false
2771
2797
  first_space = nil
2772
2798
 
2799
+ visitor = block_given? ? block : ->(elem) { visit elem }
2773
2800
  elements.each_with_index do |elem, i|
2774
2801
  @literal_elements_level = @node_level
2775
2802
 
@@ -2777,9 +2804,9 @@ class Rufo::Formatter
2777
2804
  wrote_comma = false
2778
2805
 
2779
2806
  if needs_trailing_comma
2780
- indent(needed_indent) { visit elem }
2807
+ indent(needed_indent) { visitor.call(elem) }
2781
2808
  else
2782
- visit elem
2809
+ visitor.call(elem)
2783
2810
  end
2784
2811
 
2785
2812
  # We have to be careful not to aumatically write a heredoc on next_token,
@@ -2829,6 +2856,8 @@ class Rufo::Formatter
2829
2856
  else
2830
2857
  if needs_final_space
2831
2858
  consume_space
2859
+ elsif keep_final_newline
2860
+ skip_space
2832
2861
  else
2833
2862
  skip_space_or_newline
2834
2863
  end
@@ -2938,31 +2967,55 @@ class Rufo::Formatter
2938
2967
  # [:case, cond, case_when]
2939
2968
  _, cond, case_when = node
2940
2969
 
2941
- 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
2942
2975
 
2943
2976
  if cond
2944
2977
  consume_space
2945
2978
  visit cond
2946
2979
  end
2947
2980
 
2948
- consume_end_of_line
2949
-
2950
- write_indent
2981
+ if case_expression
2982
+ consume_end_of_line
2983
+ write_indent
2984
+ else
2985
+ consume_space
2986
+ end
2951
2987
  visit case_when
2952
2988
 
2953
- write_indent
2954
- consume_keyword "end"
2989
+ if case_expression
2990
+ write_indent
2991
+ consume_keyword "end"
2992
+ end
2955
2993
  end
2956
2994
 
2957
2995
  def visit_when(node)
2958
2996
  # [:when, conds, body, next_exp]
2959
- _, conds, body, next_exp = node
2997
+ # [:in, pattern, body, next_exp]
2998
+ kw, conds_or_pattern, body, next_exp = node
2960
2999
 
2961
- 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
2962
3010
  consume_space
2963
3011
 
2964
3012
  indent(@column) do
2965
- 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
2966
3019
  skip_space
2967
3020
  end
2968
3021
  written_space = false
@@ -3020,12 +3073,15 @@ class Rufo::Formatter
3020
3073
  end
3021
3074
  end
3022
3075
 
3023
- if inline
3024
- indent do
3025
- 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
3026
3084
  end
3027
- else
3028
- indent_body body
3029
3085
  end
3030
3086
 
3031
3087
  if next_exp
@@ -3056,6 +3112,232 @@ class Rufo::Formatter
3056
3112
  end
3057
3113
  end
3058
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
+
3059
3341
  def consume_space(want_preserve_whitespace: false)
3060
3342
  first_space = skip_space
3061
3343
  if want_preserve_whitespace && !newline? && !comment? && first_space
@@ -3407,6 +3689,13 @@ class Rufo::Formatter
3407
3689
  end
3408
3690
  end
3409
3691
 
3692
+ def consume_pin_op
3693
+ return unless op?("^")
3694
+
3695
+ consume_op "^"
3696
+ skip_space
3697
+ end
3698
+
3410
3699
  def indent(value = nil)
3411
3700
  if value
3412
3701
  old_indent = @indent
@@ -3656,6 +3945,10 @@ class Rufo::Formatter
3656
3945
  current_token_kind == :on_sp
3657
3946
  end
3658
3947
 
3948
+ def op?(value)
3949
+ current_token_kind == :on_op && current_token_value == value
3950
+ end
3951
+
3659
3952
  def void_exps?(node)
3660
3953
  node.size == 1 && node[0].size == 1 && node[0][0] == :void_stmt
3661
3954
  end
@@ -3887,8 +4180,8 @@ class Rufo::Formatter
3887
4180
  end
3888
4181
 
3889
4182
  # Check to see if need to add space inside hash literal braces.
3890
- def need_space_for_hash?(node, closing_brace_token)
3891
- return false unless node[1]
4183
+ def need_space_for_hash?(node, elements, closing_brace_token)
4184
+ return false if elements.nil? || elements.empty?
3892
4185
 
3893
4186
  left_need_space = current_token_line == node_line(node, beginning: true)
3894
4187
  right_need_space = closing_brace_token[0][0] == node_line(node, beginning: false)
@@ -3901,8 +4194,16 @@ class Rufo::Formatter
3901
4194
  # get line of node, it is only used in visit_hash right now,
3902
4195
  # so handling the following node types is enough.
3903
4196
  case node.first
3904
- 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
3905
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)
3906
4207
  when :assoc_new
3907
4208
  # There's no line number info for empty strings or hashes.
3908
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.1"
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.1
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
@@ -210,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
211
  - !ruby/object:Gem::Version
211
212
  version: '0'
212
213
  requirements: []
213
- rubygems_version: 3.3.7
214
+ rubygems_version: 3.4.1
214
215
  signing_key:
215
216
  specification_version: 4
216
217
  summary: Ruby code formatter