rufo 0.1.0 → 0.2.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.
@@ -13,6 +13,6 @@ end
13
13
  require_relative "rufo/backport"
14
14
  require_relative "rufo/command"
15
15
  require_relative "rufo/dot_file"
16
+ require_relative "rufo/settings"
16
17
  require_relative "rufo/formatter"
17
- require_relative "rufo/formatter/settings"
18
18
  require_relative "rufo/version"
@@ -8,14 +8,29 @@ class Rufo::Command
8
8
  CODE_CHANGE = 3
9
9
 
10
10
  def self.run(argv)
11
- want_check, filename_for_dot_rufo = parse_options(argv)
12
- new(want_check, filename_for_dot_rufo).run(argv)
11
+ want_check, exit_code, filename_for_dot_rufo = parse_options(argv)
12
+ new(want_check, exit_code, filename_for_dot_rufo).run(argv)
13
13
  end
14
14
 
15
- def initialize(want_check, filename_for_dot_rufo)
15
+ def initialize(want_check, exit_code, filename_for_dot_rufo)
16
16
  @want_check = want_check
17
+ @exit_code = exit_code
17
18
  @filename_for_dot_rufo = filename_for_dot_rufo
18
19
  @dot_file = Rufo::DotFile.new
20
+ @squiggly_warning_files = []
21
+ end
22
+
23
+ def exit_code(status_code)
24
+ if @exit_code
25
+ status_code
26
+ else
27
+ case status_code
28
+ when CODE_OK, CODE_CHANGE
29
+ 0
30
+ else
31
+ 1
32
+ end
33
+ end
19
34
  end
20
35
 
21
36
  def run(argv)
@@ -24,8 +39,7 @@ class Rufo::Command
24
39
  else
25
40
  format_args argv
26
41
  end
27
-
28
- exit status_code
42
+ exit exit_code(status_code)
29
43
  end
30
44
 
31
45
  def format_stdin
@@ -71,6 +85,8 @@ class Rufo::Command
71
85
  syntax_error |= result == CODE_ERROR
72
86
  end
73
87
 
88
+ STDERR.puts squiggly_heredoc_warning unless @squiggly_warning_files.empty?
89
+
74
90
  case
75
91
  when syntax_error then CODE_ERROR
76
92
  when changed then CODE_CHANGE
@@ -78,11 +94,34 @@ class Rufo::Command
78
94
  end
79
95
  end
80
96
 
97
+ def squiggly_heredoc_warning
98
+ <<-EOF
99
+ Rufo Warning!
100
+ File#{squiggly_pluralize} #{squiggly_warning_files} #{squiggly_pluralize(:has)} not been formatted due to a problem with Ruby version #{RUBY_VERSION}
101
+ Please update to Ruby #{backported_version} to fix your formatting!
102
+ See https://github.com/ruby-formatter/rufo/wiki/Squiggly-Heredocs for information.
103
+ EOF
104
+ end
105
+
106
+ def squiggly_pluralize(x = :s)
107
+ idx = x == :s ? 0 : 1
108
+ (@squiggly_warning_files.length > 1 ? ["s", "have"] : ["", "has"])[idx]
109
+ end
110
+
111
+ def squiggly_warning_files
112
+ @squiggly_warning_files.join(', ')
113
+ end
114
+
115
+ def backported_version
116
+ return "2.3.5" if RUBY_VERSION[0..2] == "2.3"
117
+ "2.4.2"
118
+ end
119
+
81
120
  def format_file(filename)
82
121
  code = File.read(filename)
83
122
 
84
123
  begin
85
- result = format(code, File.dirname(filename))
124
+ result = format(code, @filename_for_dot_rufo || File.dirname(filename))
86
125
  rescue Rufo::SyntaxError
87
126
  # We ignore syntax errors as these might be template files
88
127
  # with .rb extension
@@ -94,8 +133,12 @@ class Rufo::Command
94
133
  if @want_check
95
134
  STDERR.puts "Formatting #{filename} produced changes"
96
135
  else
97
- File.write(filename, result)
98
- puts "Format: #{filename}"
136
+ unless @squiggly_warning
137
+ File.write(filename, result)
138
+ puts "Format: #{filename}"
139
+ else
140
+ @squiggly_warning_files << filename
141
+ end
99
142
  end
100
143
 
101
144
  return CODE_CHANGE
@@ -112,24 +155,21 @@ class Rufo::Command
112
155
  end
113
156
 
114
157
  def format(code, dir)
158
+ @squiggly_warning = false
115
159
  formatter = Rufo::Formatter.new(code)
116
160
 
117
- dot_rufo = @dot_file.find_in(dir)
118
- if dot_rufo
119
- begin
120
- formatter.instance_eval(dot_rufo)
121
- rescue => ex
122
- STDERR.puts "Error evaluating #{dot_rufo}"
123
- raise ex
124
- end
161
+ options = @dot_file.get_config_in(dir)
162
+ unless options.nil?
163
+ formatter.init_settings(options)
125
164
  end
126
-
127
165
  formatter.format
128
- formatter.result
166
+ result = formatter.result
167
+ @squiggly_warning = true if formatter.squiggly_flag
168
+ result
129
169
  end
130
170
 
131
171
  def self.parse_options(argv)
132
- want_check = false
172
+ exit_code, want_check = true, false
133
173
  filename_for_dot_rufo = nil
134
174
 
135
175
  OptionParser.new do |opts|
@@ -144,12 +184,16 @@ class Rufo::Command
144
184
  filename_for_dot_rufo = value
145
185
  end
146
186
 
187
+ opts.on("-x", "--simple-exit", "Return 1 in the case of failure, else 0") do
188
+ exit_code = false
189
+ end
190
+
147
191
  opts.on("-h", "--help", "Show this help") do
148
192
  puts opts
149
193
  exit
150
194
  end
151
195
  end.parse!(argv)
152
196
 
153
- [want_check, filename_for_dot_rufo]
197
+ [want_check, exit_code, filename_for_dot_rufo]
154
198
  end
155
199
  end
@@ -5,12 +5,38 @@ class Rufo::DotFile
5
5
  @cache = {}
6
6
  end
7
7
 
8
+ def get_config_in(dir)
9
+ dot_rufo = find_in(dir)
10
+ if dot_rufo
11
+ return parse(dot_rufo)
12
+ end
13
+ end
14
+
8
15
  def find_in(dir)
9
16
  @cache.fetch(dir) do
10
17
  @cache[dir] = internal_find_in(dir)
11
18
  end
12
19
  end
13
20
 
21
+ def parse(file_contents)
22
+ file_contents.lines
23
+ .map { |s| s.strip.split(/\s+/, 2) }
24
+ .each_with_object({}) do |(name, value), acc|
25
+ value ||= ''
26
+ if value.start_with?(':')
27
+ value = value[1..-1].to_sym
28
+ elsif value == 'true'
29
+ value = true
30
+ elsif value == 'false'
31
+ value = false
32
+ else
33
+ $stderr.puts "Unknown config value=#{value.inspect} for #{name.inspect}"
34
+ next
35
+ end
36
+ acc[name.to_sym] = value
37
+ end
38
+ end
39
+
14
40
  def internal_find_in(dir)
15
41
  dir = File.expand_path(dir)
16
42
  file = File.join(dir, ".rufo")
@@ -3,6 +3,12 @@
3
3
  require "ripper"
4
4
 
5
5
  class Rufo::Formatter
6
+ include Rufo::Settings
7
+
8
+ INDENT_SIZE = 2
9
+
10
+ attr_reader :squiggly_flag
11
+
6
12
  def self.format(code, **options)
7
13
  formatter = new(code, **options)
8
14
  formatter.format
@@ -10,6 +16,7 @@ class Rufo::Formatter
10
16
  end
11
17
 
12
18
  def initialize(code, **options)
19
+ @squiggly_flag = false
13
20
  @code = code
14
21
  @tokens = Ripper.lex(code).reverse!
15
22
  @sexp = Ripper.sexp(code)
@@ -55,7 +62,6 @@ class Rufo::Formatter
55
62
 
56
63
  # Are we inside a type body?
57
64
  @inside_type_body = false
58
- @visibility_indent_in_action = {}
59
65
 
60
66
  # Map lines to commands that start at the begining of a line with the following info:
61
67
  # - line indent
@@ -140,9 +146,6 @@ class Rufo::Formatter
140
146
  # and once we align the first one we fix the other ones.
141
147
  @assignments_ranges = {}
142
148
 
143
- # Hash keys positions
144
- @hash_keys_positions = []
145
-
146
149
  # Case when positions
147
150
  @case_when_positions = []
148
151
 
@@ -167,10 +170,7 @@ class Rufo::Formatter
167
170
 
168
171
  dedent_calls
169
172
  indent_literals
170
- do_align_assignments if @align_assignments
171
- do_align_hash_keys if @align_hash_keys
172
- do_align_case_when if @align_case_when
173
- do_align_comments if @align_comments
173
+ do_align_case_when if align_case_when
174
174
  remove_lines_before_inline_declarations
175
175
  end
176
176
 
@@ -231,11 +231,15 @@ class Rufo::Formatter
231
231
  when :@tstring_content
232
232
  # [:@tstring_content, "hello ", [1, 1]]
233
233
  heredoc, tilde = @current_heredoc
234
- column = node[2][0]
235
-
234
+ if heredoc && tilde && broken_ripper_version?
235
+ @squiggly_flag = true
236
+ end
236
237
  # For heredocs with tilde we sometimes need to align the contents
237
238
  if heredoc && tilde && @last_was_newline
238
- write_indent(next_indent) unless current_token_value == "\n"
239
+ unless (current_token_value == "\n" ||
240
+ current_token_kind == :on_heredoc_end)
241
+ write_indent(next_indent)
242
+ end
239
243
  skip_ignored_space
240
244
  if current_token_kind == :on_tstring_content
241
245
  check :on_tstring_content
@@ -243,7 +247,13 @@ class Rufo::Formatter
243
247
  next_token
244
248
  end
245
249
  else
246
- consume_token :on_tstring_content
250
+ while (current_token_kind == :on_ignored_sp) ||
251
+ (current_token_kind == :on_tstring_content) ||
252
+ (current_token_kind == :on_embexpr_beg)
253
+ check current_token_kind
254
+ break if current_token_kind == :on_embexpr_beg
255
+ consume_token current_token_kind
256
+ end
247
257
  end
248
258
  when :string_content
249
259
  # [:string_content, exp]
@@ -317,7 +327,6 @@ class Rufo::Formatter
317
327
  # [:vcall, exp]
318
328
  token_column = current_token_column
319
329
  visit node[1]
320
- adjust_visibility_indent(node[1], token_column)
321
330
  when :fcall
322
331
  # [:fcall, [:@ident, "foo", [1, 0]]]
323
332
  visit node[1]
@@ -447,6 +456,8 @@ class Rufo::Formatter
447
456
  visit_mlhs_add_star(node)
448
457
  when :rest_param
449
458
  visit_rest_param(node)
459
+ when :kwrest_param
460
+ visit_kwrest_param(node)
450
461
  when :retry
451
462
  # [:retry]
452
463
  consume_keyword "retry"
@@ -649,6 +660,9 @@ class Rufo::Formatter
649
660
  # [:string_embexpr, exps]
650
661
  consume_token :on_embexpr_beg
651
662
  skip_space_or_newline
663
+ if current_token_kind == :on_tstring_content
664
+ next_token
665
+ end
652
666
  visit_exps(node[1], with_lines: false)
653
667
  skip_space_or_newline
654
668
  consume_token :on_embexpr_end
@@ -722,7 +736,7 @@ class Rufo::Formatter
722
736
  line = @line
723
737
 
724
738
  visit target
725
- consume_one_dynamic_space @spaces_around_equal, force_one: @align_assignments
739
+ consume_space
726
740
 
727
741
  track_assignment
728
742
  consume_op "="
@@ -740,7 +754,7 @@ class Rufo::Formatter
740
754
  line = @line
741
755
 
742
756
  visit target
743
- consume_one_dynamic_space @spaces_around_equal, force_one: @align_assignments
757
+ consume_space
744
758
 
745
759
  # [:@op, "+=", [1, 2]],
746
760
  check :on_op
@@ -772,11 +786,7 @@ class Rufo::Formatter
772
786
  first_space = skip_space
773
787
  end
774
788
 
775
- if @align_assignments
776
- write_space
777
- else
778
- write_space_using_setting(first_space, @spaces_around_equal)
779
- end
789
+ write_space_using_setting(first_space, :one)
780
790
 
781
791
  track_assignment
782
792
  consume_op "="
@@ -799,11 +809,9 @@ class Rufo::Formatter
799
809
  visit(value)
800
810
  end
801
811
  else
802
- want_space = first_space || @spaces_around_equal == :one
803
812
  indent_after_space value, sticky: sticky,
804
- want_space: want_space,
805
- first_space: first_space,
806
- preserve_whitespace: @spaces_around_equal == :dynamic && !@align_assignments
813
+ want_space: true,
814
+ first_space: first_space
807
815
  end
808
816
  end
809
817
 
@@ -846,12 +854,6 @@ class Rufo::Formatter
846
854
  track_alignment :assign, @assignments_positions, offset
847
855
  end
848
856
 
849
- def track_hash_key
850
- return unless @current_hash
851
-
852
- track_alignment :hash_key, @hash_keys_positions, 0, @current_hash.object_id
853
- end
854
-
855
857
  def track_case_when
856
858
  track_alignment :case_whem, @case_when_positions
857
859
  end
@@ -876,13 +878,13 @@ class Rufo::Formatter
876
878
  _, cond, then_body, else_body = node
877
879
 
878
880
  visit cond
879
- consume_one_dynamic_space @spaces_in_ternary
881
+ consume_space
880
882
  consume_op "?"
881
- consume_one_dynamic_space_or_newline @spaces_in_ternary
883
+ consume_space_or_newline
882
884
  visit then_body
883
- consume_one_dynamic_space @spaces_in_ternary
885
+ consume_space
884
886
  consume_op ":"
885
- consume_one_dynamic_space_or_newline @spaces_in_ternary
887
+ consume_space_or_newline
886
888
  visit else_body
887
889
  end
888
890
 
@@ -899,9 +901,9 @@ class Rufo::Formatter
899
901
  end
900
902
 
901
903
  visit body
902
- consume_one_dynamic_space @spaces_in_suffix
904
+ consume_space
903
905
  consume_keyword(suffix)
904
- consume_one_dynamic_space_or_newline @spaces_in_suffix
906
+ consume_space_or_newline
905
907
  visit cond
906
908
  end
907
909
 
@@ -917,8 +919,8 @@ class Rufo::Formatter
917
919
  if newline? || comment?
918
920
  consume_end_of_line
919
921
 
920
- # If align_chained_calls if off, we still want to preserve alignment if it's already there
921
- if @align_chained_calls || (@original_dot_column && @original_dot_column == current_token_column)
922
+ # If align_chained_calls is off, we still want to preserve alignment if it's already there
923
+ if align_chained_calls || (@original_dot_column && @original_dot_column == current_token_column)
922
924
  @name_dot_column = @dot_column || next_indent
923
925
  write_indent(@dot_column || next_indent)
924
926
  else
@@ -928,7 +930,7 @@ class Rufo::Formatter
928
930
  write_indent(next_indent)
929
931
  end
930
932
  else
931
- write_space_using_setting(first_space, @spaces_around_dot)
933
+ write_space_using_setting(first_space, :no)
932
934
  end
933
935
 
934
936
  # Remember dot column, but only if there isn't one already set
@@ -939,7 +941,7 @@ class Rufo::Formatter
939
941
 
940
942
  consume_call_dot
941
943
 
942
- skip_space_or_newline_using_setting(@spaces_around_dot, next_indent)
944
+ skip_space_or_newline_using_setting(:no, next_indent)
943
945
 
944
946
  if name == :call
945
947
  # :call means it's .()
@@ -1030,7 +1032,7 @@ class Rufo::Formatter
1030
1032
 
1031
1033
  if found_comma
1032
1034
  if needs_trailing_newline
1033
- write "," if @trailing_commas != :never && !block_arg
1035
+ write "," if trailing_commas && !block_arg
1034
1036
 
1035
1037
  next_token
1036
1038
  indent(next_indent) do
@@ -1045,7 +1047,7 @@ class Rufo::Formatter
1045
1047
 
1046
1048
  if newline? || comment?
1047
1049
  if needs_trailing_newline
1048
- write "," if @trailing_commas == :always && want_trailing_comma
1050
+ write "," if trailing_commas && want_trailing_comma
1049
1051
 
1050
1052
  indent(next_indent) do
1051
1053
  consume_end_of_line
@@ -1056,7 +1058,7 @@ class Rufo::Formatter
1056
1058
  end
1057
1059
  else
1058
1060
  if needs_trailing_newline && !found_comma
1059
- write "," if @trailing_commas == :always && want_trailing_comma
1061
+ write "," if trailing_commas && want_trailing_comma
1060
1062
  consume_end_of_line
1061
1063
  write_indent
1062
1064
  end
@@ -1071,6 +1073,9 @@ class Rufo::Formatter
1071
1073
  call_info << @line
1072
1074
  end
1073
1075
 
1076
+ if @last_was_heredoc
1077
+ write_line
1078
+ end
1074
1079
  consume_token :on_rparen
1075
1080
  end
1076
1081
 
@@ -1118,6 +1123,8 @@ class Rufo::Formatter
1118
1123
  @current_heredoc = nil
1119
1124
  printed = true
1120
1125
  end
1126
+
1127
+ @last_was_heredoc = true if printed
1121
1128
  end
1122
1129
 
1123
1130
  def visit_command_call(node)
@@ -1167,7 +1174,7 @@ class Rufo::Formatter
1167
1174
  write_line
1168
1175
  write_indent(next_indent)
1169
1176
  else
1170
- write_space_using_setting(first_space, @spaces_in_commands)
1177
+ write_space_using_setting(first_space, :one)
1171
1178
  end
1172
1179
  end
1173
1180
 
@@ -1232,7 +1239,7 @@ class Rufo::Formatter
1232
1239
  #
1233
1240
  # foo 1,
1234
1241
  # 2
1235
- elsif !args_is_def_class_or_module && @first_token_in_line && base_column + @indent_size == @first_token_in_line[0][1]
1242
+ elsif !args_is_def_class_or_module && @first_token_in_line && base_column + INDENT_SIZE == @first_token_in_line[0][1]
1236
1243
  # Otherwise, align it just by two spaces (so we need to dedent, we fake a dedent here)
1237
1244
  #
1238
1245
  # foo 1,
@@ -1250,7 +1257,7 @@ class Rufo::Formatter
1250
1257
  visit call
1251
1258
 
1252
1259
  if block[0] == :brace_block
1253
- consume_one_dynamic_space @spaces_around_block_brace
1260
+ consume_space
1254
1261
  else
1255
1262
  consume_space
1256
1263
  end
@@ -1272,7 +1279,7 @@ class Rufo::Formatter
1272
1279
  if void_exps?(body)
1273
1280
  consume_token :on_lbrace
1274
1281
  consume_block_args args
1275
- consume_one_dynamic_space @spaces_around_block_brace
1282
+ consume_space
1276
1283
  consume_token :on_rbrace
1277
1284
  return
1278
1285
  end
@@ -1283,14 +1290,14 @@ class Rufo::Formatter
1283
1290
  if current_token_line == closing_brace_token[0][0]
1284
1291
  consume_token :on_lbrace
1285
1292
  consume_block_args args
1286
- consume_one_dynamic_space @spaces_around_block_brace
1293
+ consume_space
1287
1294
  visit_exps body, with_lines: false
1288
1295
 
1289
1296
  while semicolon?
1290
1297
  next_token
1291
1298
  end
1292
1299
 
1293
- consume_one_dynamic_space @spaces_around_block_brace
1300
+ consume_space
1294
1301
 
1295
1302
  consume_token :on_rbrace
1296
1303
  return
@@ -1337,7 +1344,7 @@ class Rufo::Formatter
1337
1344
 
1338
1345
  def consume_block_args(args)
1339
1346
  if args
1340
- consume_one_dynamic_space_or_newline @spaces_around_block_brace
1347
+ consume_space_or_newline
1341
1348
  # + 1 because of |...|
1342
1349
  # ^
1343
1350
  indent(@column + 1) do
@@ -1470,7 +1477,7 @@ class Rufo::Formatter
1470
1477
 
1471
1478
  line = @line
1472
1479
 
1473
- indent_body body, want_multiline: inside_type_body && @double_newline_inside_type == :dynamic
1480
+ indent_body body
1474
1481
 
1475
1482
  while rescue_body
1476
1483
  # [:rescue, type, name, body, more_rescue]
@@ -1512,11 +1519,6 @@ class Rufo::Formatter
1512
1519
  indent_body ensure_body[1]
1513
1520
  end
1514
1521
 
1515
- if inside_type_body && current_type && @visibility_indent_in_action[current_type]
1516
- @indent -= @indent_size
1517
- @visibility_indent_in_action.delete current_type
1518
- end
1519
-
1520
1522
  write_indent if @line != line
1521
1523
  consume_keyword "end"
1522
1524
  end
@@ -1614,6 +1616,13 @@ class Rufo::Formatter
1614
1616
  consume_space
1615
1617
 
1616
1618
  visit_comma_separated_list to_ary(var)
1619
+ skip_space
1620
+ if comma?
1621
+ check :on_comma
1622
+ write ','
1623
+ next_token
1624
+ skip_space_or_newline
1625
+ end
1617
1626
 
1618
1627
  consume_space
1619
1628
  consume_keyword "in"
@@ -1664,9 +1673,9 @@ class Rufo::Formatter
1664
1673
  needs_indent = false
1665
1674
 
1666
1675
  if newline? || comment?
1676
+ indent { consume_end_of_line }
1667
1677
  needs_indent = true
1668
1678
  base_column = next_indent
1669
- consume_end_of_line
1670
1679
  write_indent(base_column)
1671
1680
  else
1672
1681
  base_column = @column
@@ -1688,7 +1697,7 @@ class Rufo::Formatter
1688
1697
  check :on_comma
1689
1698
  write ","
1690
1699
  next_token
1691
- skip_space_or_newline_using_setting(@spaces_after_comma, base_column || @indent)
1700
+ skip_space_or_newline_using_setting(:one, base_column || @indent)
1692
1701
  end
1693
1702
  end
1694
1703
 
@@ -1734,21 +1743,27 @@ class Rufo::Formatter
1734
1743
  end
1735
1744
  end
1736
1745
 
1746
+ def visit_kwrest_param(node)
1747
+ # [:kwrest_param, name]
1748
+
1749
+ _, name = node
1750
+
1751
+ if name
1752
+ skip_space_or_newline
1753
+ visit name
1754
+ end
1755
+ end
1756
+
1737
1757
  def visit_unary(node)
1738
1758
  # [:unary, :-@, [:vcall, [:@ident, "x", [1, 2]]]]
1739
1759
  _, op, exp = node
1740
1760
 
1741
1761
  consume_op_or_keyword op
1742
1762
 
1743
- setting = op == :not ? @spaces_in_commands : @spaces_around_unary
1763
+ setting = op == :not ? :one : :no
1744
1764
 
1745
1765
  first_space = space?
1746
- consume_space = first_space && setting == :dynamic
1747
- if consume_space
1748
- consume_space(want_preserve_whitespace: true)
1749
- else
1750
- skip_space_or_newline
1751
- end
1766
+ skip_space_or_newline
1752
1767
 
1753
1768
  if op == :not
1754
1769
  has_paren = current_token_kind == :on_lparen
@@ -1804,10 +1819,8 @@ class Rufo::Formatter
1804
1819
  write " \\"
1805
1820
  write_line
1806
1821
  write_indent(next_indent)
1807
- elsif first_space && @spaces_around_binary == :dynamic
1808
- write_space first_space[2]
1809
1822
  else
1810
- write_space if needs_space
1823
+ write_space
1811
1824
  end
1812
1825
 
1813
1826
  consume_op_or_keyword op
@@ -1819,14 +1832,9 @@ class Rufo::Formatter
1819
1832
  want_space: needs_space,
1820
1833
  needed_indent: needed_indent,
1821
1834
  token_column: token_column,
1822
- base_column: base_column,
1823
- preserve_whitespace: @spaces_around_binary == :dynamic
1835
+ base_column: base_column
1824
1836
  else
1825
- if @spaces_around_binary == :one
1826
- write " " if needs_space
1827
- elsif first_space
1828
- write_space first_space[2]
1829
- end
1837
+ write_space
1830
1838
  visit right
1831
1839
  end
1832
1840
  end
@@ -1940,11 +1948,8 @@ class Rufo::Formatter
1940
1948
  skip_space_or_newline
1941
1949
  check :on_rparen
1942
1950
  next_token
1943
- write_space_using_setting(first_space, @spaces_after_method_name)
1944
1951
  write "()"
1945
1952
  else
1946
- write_space_using_setting(first_space, @spaces_after_method_name)
1947
-
1948
1953
  write "("
1949
1954
 
1950
1955
  if newline? || comment?
@@ -1966,14 +1971,14 @@ class Rufo::Formatter
1966
1971
  next_token
1967
1972
  end
1968
1973
  elsif !empty_params?(params)
1969
- if @parens_in_def == :yes
1974
+ if parens_in_def == :yes
1970
1975
  write "("
1971
1976
  else
1972
1977
  write_space
1973
1978
  end
1974
1979
 
1975
1980
  visit params
1976
- write ")" if @parens_in_def == :yes
1981
+ write ")" if parens_in_def == :yes
1977
1982
  skip_space
1978
1983
  end
1979
1984
 
@@ -2019,9 +2024,9 @@ class Rufo::Formatter
2019
2024
  write_params_comma if needs_comma
2020
2025
  visit_comma_separated_list(args_with_default) do |arg, default|
2021
2026
  visit arg
2022
- consume_one_dynamic_space @spaces_around_equal
2027
+ consume_space
2023
2028
  consume_op "="
2024
- consume_one_dynamic_space @spaces_around_equal
2029
+ consume_space
2025
2030
  visit default
2026
2031
  end
2027
2032
  needs_comma = true
@@ -2058,7 +2063,6 @@ class Rufo::Formatter
2058
2063
  skip_space_or_newline
2059
2064
  if value
2060
2065
  consume_space
2061
- track_hash_key
2062
2066
  visit value
2063
2067
  end
2064
2068
  end
@@ -2091,7 +2095,7 @@ class Rufo::Formatter
2091
2095
  check :on_comma
2092
2096
  write ","
2093
2097
  next_token
2094
- skip_space_or_newline_using_setting(@spaces_after_comma)
2098
+ skip_space_or_newline_using_setting(:one)
2095
2099
  end
2096
2100
 
2097
2101
  def visit_array(node)
@@ -2235,15 +2239,13 @@ class Rufo::Formatter
2235
2239
  arrow = symbol || !(key[0] == :@label || key[0] == :dyna_symbol)
2236
2240
 
2237
2241
  visit key
2238
- consume_one_dynamic_space @spaces_around_hash_arrow
2239
-
2240
- track_hash_key
2242
+ consume_space
2241
2243
 
2242
2244
  # Don't output `=>` for keys that are `label: value`
2243
2245
  # or `"label": value`
2244
2246
  if arrow
2245
2247
  consume_op "=>"
2246
- consume_one_dynamic_space @spaces_around_hash_arrow, force_one: @align_hash_keys
2248
+ consume_space
2247
2249
  end
2248
2250
 
2249
2251
  visit value
@@ -2329,7 +2331,7 @@ class Rufo::Formatter
2329
2331
  skip_space_or_newline
2330
2332
  end
2331
2333
  else
2332
- write_space_using_setting(first_space, @spaces_inside_array_bracket)
2334
+ write_space_using_setting(first_space, :never)
2333
2335
  needed_indent = column
2334
2336
  end
2335
2337
 
@@ -2340,7 +2342,7 @@ class Rufo::Formatter
2340
2342
  end
2341
2343
  end
2342
2344
 
2343
- skip_space_or_newline_using_setting(@spaces_inside_array_bracket)
2345
+ skip_space_or_newline_using_setting(:never)
2344
2346
 
2345
2347
  check :on_rbracket
2346
2348
  write "]"
@@ -2377,7 +2379,7 @@ class Rufo::Formatter
2377
2379
 
2378
2380
  visit receiver
2379
2381
 
2380
- skip_space_or_newline_using_setting(@spaces_around_dot, @dot_column || next_indent)
2382
+ skip_space_or_newline_using_setting(:no, @dot_column || next_indent)
2381
2383
 
2382
2384
  # Remember dot column
2383
2385
  dot_column = @column
@@ -2385,7 +2387,7 @@ class Rufo::Formatter
2385
2387
 
2386
2388
  consume_call_dot
2387
2389
 
2388
- skip_space_or_newline_using_setting(@spaces_around_dot, next_indent)
2390
+ skip_space_or_newline_using_setting(:no, next_indent)
2389
2391
 
2390
2392
  visit name
2391
2393
 
@@ -2438,7 +2440,7 @@ class Rufo::Formatter
2438
2440
  next_token
2439
2441
 
2440
2442
  first_space = skip_space
2441
- write_space_using_setting(first_space, @spaces_after_lambda_arrow)
2443
+ write_space_using_setting(first_space, :one)
2442
2444
 
2443
2445
  if empty_params?(params)
2444
2446
  if current_token_kind == :on_lparen
@@ -2469,9 +2471,9 @@ class Rufo::Formatter
2469
2471
  if current_token_line == closing_brace_token[0][0]
2470
2472
  consume_token :on_tlambeg
2471
2473
 
2472
- consume_space unless !space? && @spaces_around_block_brace == :dynamic
2474
+ consume_space
2473
2475
  visit_exps body, with_lines: false
2474
- consume_space unless !space? && @spaces_around_block_brace == :dynamic
2476
+ consume_space
2475
2477
 
2476
2478
  consume_token :on_rbrace
2477
2479
  return
@@ -2517,7 +2519,7 @@ class Rufo::Formatter
2517
2519
  has_space = space?
2518
2520
 
2519
2521
  if has_space
2520
- consume_space(want_preserve_whitespace: @spaces_in_commands == :dynamic)
2522
+ consume_space
2521
2523
  else
2522
2524
  skip_space_or_newline
2523
2525
  end
@@ -2567,34 +2569,15 @@ class Rufo::Formatter
2567
2569
  first_space = skip_space
2568
2570
 
2569
2571
  if inside_hash
2570
- case @spaces_inside_hash_brace
2571
- when :never
2572
- needs_final_space = false
2573
- when :always
2574
- needs_final_space = true
2575
- end
2572
+ needs_final_space = false
2576
2573
  end
2577
2574
 
2578
2575
  if inside_array
2579
- case @spaces_inside_array_bracket
2580
- when :never
2581
- needs_final_space = false
2582
- when :always
2583
- needs_final_space = true
2584
- end
2576
+ needs_final_space = false
2585
2577
  end
2586
2578
 
2587
2579
  if newline? || comment?
2588
2580
  needs_final_space = false
2589
- elsif needs_final_space
2590
- if inside_hash && first_space && @spaces_inside_hash_brace == :dynamic
2591
- write first_space[2]
2592
- elsif inside_array && first_space && @spaces_inside_array_bracket == :dynamic
2593
- write first_space[2]
2594
- else
2595
- consume_space
2596
- end
2597
- base_column = @column
2598
2581
  end
2599
2582
 
2600
2583
  # If there's a newline right at the beginning,
@@ -2614,13 +2597,11 @@ class Rufo::Formatter
2614
2597
  end
2615
2598
 
2616
2599
  wrote_comma = false
2617
- last_has_comma = false
2618
2600
  first_space = nil
2619
2601
 
2620
2602
  elements.each_with_index do |elem, i|
2621
2603
  is_last = last?(i, elements)
2622
2604
  wrote_comma = false
2623
- last_has_comma = false
2624
2605
 
2625
2606
  if needs_trailing_comma
2626
2607
  indent(needed_indent) { visit elem }
@@ -2633,21 +2614,8 @@ class Rufo::Formatter
2633
2614
  first_space = skip_space_no_heredoc_check
2634
2615
  wrote_comma = check_heredocs_in_literal_elements(is_last, needs_trailing_comma, wrote_comma)
2635
2616
 
2636
- if is_last && !comma? && !wrote_comma && !needs_trailing_comma && !comment?
2637
- if (inside_hash && @spaces_inside_hash_brace == :dynamic) ||
2638
- (inside_array && @spaces_inside_array_bracket == :dynamic)
2639
- if first_space
2640
- write first_space[2]
2641
- else
2642
- needs_final_space = false
2643
- end
2644
- end
2645
- end
2646
-
2647
2617
  next unless comma?
2648
2618
 
2649
- last_has_comma = true
2650
-
2651
2619
  unless is_last
2652
2620
  write ","
2653
2621
  wrote_comma = true
@@ -2669,22 +2637,13 @@ class Rufo::Formatter
2669
2637
  write_indent
2670
2638
  end
2671
2639
  end
2672
- elsif !is_last && first_space && @spaces_after_comma == :dynamic
2673
- write_space first_space[2]
2674
- elsif @spaces_after_comma == :one
2640
+ else
2675
2641
  write_space unless is_last
2676
2642
  end
2677
2643
  end
2678
2644
 
2679
2645
  if needs_trailing_comma
2680
- case @trailing_commas
2681
- when :always
2682
- write "," unless wrote_comma
2683
- when :never
2684
- # Nothing
2685
- when :dynamic
2686
- write "," if last_has_comma && !wrote_comma
2687
- end
2646
+ write "," unless wrote_comma || !trailing_commas
2688
2647
 
2689
2648
  consume_end_of_line(first_space: first_space)
2690
2649
  write_indent
@@ -2705,7 +2664,7 @@ class Rufo::Formatter
2705
2664
  # foo([
2706
2665
  # 2,
2707
2666
  # ])
2708
- @literal_indents << [base_line, @line, token_column + @indent_size - needed_indent]
2667
+ @literal_indents << [base_line, @line, token_column + INDENT_SIZE - needed_indent]
2709
2668
  elsif call_info && call_info[0] == current_token_column
2710
2669
  # If the closing literal position matches the column where
2711
2670
  # the call started, we want to preserve it like that
@@ -2822,16 +2781,13 @@ class Rufo::Formatter
2822
2781
  # [:when, conds, body, next_exp]
2823
2782
  _, conds, body, next_exp = node
2824
2783
 
2825
- preserve_whitespace = @spaces_around_when == :dynamic && !@align_case_when
2826
-
2827
2784
  consume_keyword "when"
2828
- consume_space(want_preserve_whitespace: preserve_whitespace)
2785
+ consume_space
2829
2786
 
2830
2787
  space_after_when = nil
2831
2788
 
2832
2789
  indent(@column) do
2833
2790
  visit_comma_separated_list conds
2834
- space_after_when = current_token if space? && preserve_whitespace
2835
2791
  skip_space
2836
2792
  end
2837
2793
 
@@ -2840,7 +2796,6 @@ class Rufo::Formatter
2840
2796
  if then_keyword
2841
2797
  next_token
2842
2798
 
2843
- space_after_then = current_token if space? && preserve_whitespace
2844
2799
  skip_space
2845
2800
 
2846
2801
  info = track_case_when
@@ -2852,11 +2807,7 @@ class Rufo::Formatter
2852
2807
  # Cancel tracking of `case when ... then` on a nelwine.
2853
2808
  @case_when_positions.pop
2854
2809
  else
2855
- if space_after_when
2856
- write_space space_after_when[2]
2857
- else
2858
- write_space
2859
- end
2810
+ write_space
2860
2811
 
2861
2812
  write "then"
2862
2813
 
@@ -2877,11 +2828,7 @@ class Rufo::Formatter
2877
2828
  info[-1] = offset
2878
2829
  end
2879
2830
 
2880
- if space_after_then
2881
- write_space space_after_then[2]
2882
- else
2883
- write_space
2884
- end
2831
+ write_space
2885
2832
  end
2886
2833
  elsif semicolon?
2887
2834
  skip_semicolons
@@ -2918,10 +2865,10 @@ class Rufo::Formatter
2918
2865
 
2919
2866
  indent_body next_exp[1]
2920
2867
  else
2921
- if @align_case_when
2868
+ if align_case_when
2922
2869
  write_space
2923
2870
  else
2924
- write_space_using_setting(first_space, @spaces_around_when)
2871
+ write_space_using_setting(first_space, :one)
2925
2872
  end
2926
2873
  visit_exps next_exp[1]
2927
2874
  end
@@ -2942,33 +2889,13 @@ class Rufo::Formatter
2942
2889
  end
2943
2890
  end
2944
2891
 
2945
- def consume_one_dynamic_space(setting, force_one: false)
2946
- if setting == :one || force_one
2947
- consume_space
2948
- else
2949
- if space?
2950
- consume_space(want_preserve_whitespace: true)
2951
- elsif newline?
2952
- next_token
2953
- if space?
2954
- write_space current_token[2]
2955
- end
2956
- skip_space_or_newline
2957
- else
2958
- skip_space_or_newline
2959
- end
2960
- end
2961
- end
2962
-
2963
- def consume_one_dynamic_space_or_newline(setting)
2892
+ def consume_space_or_newline
2964
2893
  first_space = skip_space
2965
2894
  if newline? || comment?
2966
2895
  consume_end_of_line
2967
2896
  write_indent(next_indent)
2968
- elsif first_space && setting == :dynamic
2969
- write_space first_space[2]
2970
2897
  else
2971
- consume_space if setting == :one
2898
+ consume_space
2972
2899
  end
2973
2900
  end
2974
2901
 
@@ -3028,8 +2955,11 @@ class Rufo::Formatter
3028
2955
 
3029
2956
  write_indent if found_comment
3030
2957
  if current_token_value.end_with?("\n")
2958
+ write_space
3031
2959
  write current_token_value.rstrip
3032
- write_line
2960
+ write "\n"
2961
+ write_indent(next_indent)
2962
+ @column = next_indent
3033
2963
  else
3034
2964
  write current_token_value
3035
2965
  end
@@ -3201,7 +3131,7 @@ class Rufo::Formatter
3201
3131
  # so append a space if needed (for example after an expression)
3202
3132
  unless at_prefix
3203
3133
  # Preserve whitespace before comment unless we need to align them
3204
- if last_space && !@align_comments
3134
+ if last_space
3205
3135
  write last_space[2]
3206
3136
  else
3207
3137
  write_space
@@ -3312,13 +3242,13 @@ class Rufo::Formatter
3312
3242
  yield
3313
3243
  @indent = old_indent
3314
3244
  else
3315
- @indent += @indent_size
3245
+ @indent += INDENT_SIZE
3316
3246
  yield
3317
- @indent -= @indent_size
3247
+ @indent -= INDENT_SIZE
3318
3248
  end
3319
3249
  end
3320
3250
 
3321
- def indent_body(exps, force_multiline: false, want_multiline: false)
3251
+ def indent_body(exps, force_multiline: false)
3322
3252
  first_space = skip_space
3323
3253
 
3324
3254
  has_semicolon = semicolon?
@@ -3334,7 +3264,7 @@ class Rufo::Formatter
3334
3264
  if has_semicolon
3335
3265
  write "; "
3336
3266
  else
3337
- write_space_using_setting(first_space, @spaces_in_inline_expressions)
3267
+ write_space_using_setting(first_space, :one)
3338
3268
  end
3339
3269
  return
3340
3270
  end
@@ -3359,28 +3289,23 @@ class Rufo::Formatter
3359
3289
  if has_then
3360
3290
  write " then "
3361
3291
  elsif has_do
3362
- write_space_using_setting(first_space, @spaces_in_inline_expressions, at_least_one: true)
3292
+ write_space_using_setting(first_space, :one, at_least_one: true)
3363
3293
  write "do"
3364
- write_space_using_setting(second_space, @spaces_in_inline_expressions, at_least_one: true)
3294
+ write_space_using_setting(second_space, :one, at_least_one: true)
3365
3295
  elsif has_semicolon
3366
3296
  write "; "
3367
3297
  else
3368
- write_space_using_setting(first_space, @spaces_in_inline_expressions, at_least_one: true)
3298
+ write_space_using_setting(first_space, :one, at_least_one: true)
3369
3299
  end
3370
3300
  visit_exps exps, with_indent: false, with_lines: false
3371
3301
 
3372
- first_space = skip_space
3373
- if first_space && @spaces_in_inline_expressions == :dynamic &&
3374
- !(semicolon? || newline? || comment?)
3375
- write_space first_space[2]
3376
- else
3377
- consume_space
3378
- end
3302
+ consume_space
3303
+
3379
3304
  return
3380
3305
  end
3381
3306
 
3382
3307
  indent do
3383
- consume_end_of_line(want_multiline: want_multiline)
3308
+ consume_end_of_line(want_multiline: false)
3384
3309
  end
3385
3310
 
3386
3311
  if keyword?("then")
@@ -3394,7 +3319,7 @@ class Rufo::Formatter
3394
3319
  skip_space_or_newline
3395
3320
  else
3396
3321
  indent do
3397
- visit_exps exps, with_indent: true, want_trailing_multiline: want_multiline
3322
+ visit_exps exps, with_indent: true
3398
3323
  end
3399
3324
  write_line unless @last_was_newline
3400
3325
  end
@@ -3413,6 +3338,7 @@ class Rufo::Formatter
3413
3338
  def write(value)
3414
3339
  @output << value
3415
3340
  @last_was_newline = false
3341
+ @last_was_heredoc = false
3416
3342
  @column += value.size
3417
3343
  end
3418
3344
 
@@ -3453,7 +3379,7 @@ class Rufo::Formatter
3453
3379
  @column += indent
3454
3380
  end
3455
3381
 
3456
- def indent_after_space(node, sticky: false, want_space: true, first_space: nil, needed_indent: next_indent, token_column: nil, base_column: nil, preserve_whitespace:)
3382
+ def indent_after_space(node, sticky: false, want_space: true, first_space: nil, needed_indent: next_indent, token_column: nil, base_column: nil)
3457
3383
  first_space = current_token if space?
3458
3384
  skip_space
3459
3385
 
@@ -3477,11 +3403,7 @@ class Rufo::Formatter
3477
3403
  end
3478
3404
  else
3479
3405
  if want_space
3480
- if first_space && preserve_whitespace
3481
- write_space first_space[2]
3482
- else
3483
- write_space
3484
- end
3406
+ write_space
3485
3407
  end
3486
3408
  if sticky
3487
3409
  indent(@column) do
@@ -3494,7 +3416,7 @@ class Rufo::Formatter
3494
3416
  end
3495
3417
 
3496
3418
  def next_indent
3497
- @indent + @indent_size
3419
+ @indent + INDENT_SIZE
3498
3420
  end
3499
3421
 
3500
3422
  def check(kind)
@@ -3558,64 +3480,6 @@ class Rufo::Formatter
3558
3480
  node.size == 1 && node[0].size == 1 && node[0][0] == :void_stmt
3559
3481
  end
3560
3482
 
3561
- def adjust_visibility_indent(node, base_column)
3562
- return if @visibility_indent == :align
3563
-
3564
- case node[1]
3565
- when "private", "protected", "public"
3566
- # OK
3567
- else
3568
- return
3569
- end
3570
-
3571
- i = @tokens.size - 1
3572
-
3573
- # First, skip spaces until a newline or comment
3574
- while i >= 0
3575
- token = @tokens[i]
3576
- case token[1]
3577
- when :on_sp
3578
- i -= 1
3579
- next
3580
- when :on_nl, :on_ignored_nl, :on_comment
3581
- i -= 1
3582
- break
3583
- else
3584
- return
3585
- end
3586
- end
3587
-
3588
- if @visibility_indent_in_action[@current_type]
3589
- last_newline_index = @output.rindex("\n")
3590
- if last_newline_index
3591
- # Remove extra indent if we are indenting inside private/protected/public
3592
- # and we just found another one.
3593
- @output = "#{@output[0..last_newline_index]}#{@output[last_newline_index + 1 + @indent_size..-1]}".dup
3594
- @indent -= @indent_size
3595
- @visibility_indent_in_action.delete @current_type
3596
- end
3597
- end
3598
-
3599
- # Now we skip all spaces and newlines
3600
- while i >= 0
3601
- token = @tokens[i]
3602
- case token[1]
3603
- when :on_sp, :on_nl, :on_ignored_nl
3604
- i -= 1
3605
- next
3606
- else
3607
- break
3608
- end
3609
- end
3610
-
3611
- return if i < 0
3612
-
3613
- if @visibility_indent == :indent || base_column + @indent_size == @tokens[i][0][1]
3614
- @indent += @indent_size
3615
- @visibility_indent_in_action[@current_type] = true
3616
- end
3617
- end
3618
-
3619
3483
  def find_closing_brace_token
3620
3484
  count = 0
3621
3485
  i = @tokens.size - 1
@@ -3739,7 +3603,7 @@ class Rufo::Formatter
3739
3603
  next if @unmodifiable_string_lines[line]
3740
3604
 
3741
3605
  current_line = lines[line]
3742
- current_line = current_line[diff..-1]
3606
+ current_line = current_line[diff..-1] if diff >= 0
3743
3607
 
3744
3608
  # It can happen that this line didn't need an indent because
3745
3609
  # it simply had a newline
@@ -3772,18 +3636,6 @@ class Rufo::Formatter
3772
3636
  @output = lines.join
3773
3637
  end
3774
3638
 
3775
- def do_align_comments
3776
- do_align @comments_positions, :comment
3777
- end
3778
-
3779
- def do_align_assignments
3780
- do_align @assignments_positions, :assign
3781
- end
3782
-
3783
- def do_align_hash_keys
3784
- do_align @hash_keys_positions, :hash_key
3785
- end
3786
-
3787
3639
  def do_align_case_when
3788
3640
  do_align @case_when_positions, :case
3789
3641
  end
@@ -3799,16 +3651,6 @@ class Rufo::Formatter
3799
3651
  chunks.each do |elements|
3800
3652
  next if elements.size == 1
3801
3653
 
3802
- if scope == :hash_key
3803
- # Don't indent successive hash keys if any of them is in turn a hash
3804
- # or array literal that is formatted in separate lines.
3805
- has_brace_newline = elements.any? do |(l, c)|
3806
- line_end = lines[l][c..-1]
3807
- line_end.start_with?("=> {\n", "=> [\n", "=> [ #", "=> { #", "[\n", "{\n", "[ #", "{ #")
3808
- end
3809
- next if has_brace_newline
3810
- end
3811
-
3812
3654
  max_column = elements.map { |l, c| c }.max
3813
3655
 
3814
3656
  elements.each do |(line, column, _, _, offset)|
@@ -3867,6 +3709,12 @@ class Rufo::Formatter
3867
3709
  end
3868
3710
  end
3869
3711
 
3712
+ def broken_ripper_version?
3713
+ version, teeny = RUBY_VERSION[0..2], RUBY_VERSION[4..4].to_i
3714
+ (version == "2.3" && teeny < 5) ||
3715
+ (version == "2.4" && teeny < 2)
3716
+ end
3717
+
3870
3718
  def remove_lines_before_inline_declarations
3871
3719
  return if @inline_declarations.empty?
3872
3720