ripper_ruby_parser 1.6.0 → 1.8.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -0
  3. data/README.md +8 -25
  4. data/lib/ripper_ruby_parser.rb +2 -2
  5. data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +54 -23
  6. data/lib/ripper_ruby_parser/parser.rb +3 -3
  7. data/lib/ripper_ruby_parser/sexp_handlers.rb +11 -9
  8. data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +10 -11
  9. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +48 -63
  10. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +17 -19
  11. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +35 -2
  12. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +15 -242
  13. data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +4 -2
  14. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +1 -1
  15. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +24 -24
  16. data/lib/ripper_ruby_parser/sexp_handlers/string_literals.rb +266 -0
  17. data/lib/ripper_ruby_parser/sexp_processor.rb +47 -78
  18. data/lib/ripper_ruby_parser/unescape.rb +79 -50
  19. data/lib/ripper_ruby_parser/version.rb +1 -1
  20. metadata +115 -78
  21. data/Rakefile +0 -33
  22. data/test/end_to_end/comments_test.rb +0 -59
  23. data/test/end_to_end/comparison_test.rb +0 -104
  24. data/test/end_to_end/lib_comparison_test.rb +0 -29
  25. data/test/end_to_end/line_numbering_test.rb +0 -64
  26. data/test/end_to_end/samples_comparison_test.rb +0 -13
  27. data/test/end_to_end/test_comparison_test.rb +0 -32
  28. data/test/pt_testcase/pt_test.rb +0 -44
  29. data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +0 -190
  30. data/test/ripper_ruby_parser/parser_test.rb +0 -469
  31. data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +0 -649
  32. data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +0 -661
  33. data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +0 -536
  34. data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +0 -1117
  35. data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +0 -209
  36. data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +0 -267
  37. data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +0 -427
  38. data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +0 -399
  39. data/test/ripper_ruby_parser/sexp_processor_test.rb +0 -303
  40. data/test/ripper_ruby_parser/version_test.rb +0 -7
  41. data/test/samples/assignment.rb +0 -17
  42. data/test/samples/comments.rb +0 -13
  43. data/test/samples/conditionals.rb +0 -23
  44. data/test/samples/loops.rb +0 -36
  45. data/test/samples/misc.rb +0 -278
  46. data/test/samples/number.rb +0 -7
  47. data/test/samples/operators.rb +0 -18
  48. data/test/samples/strings.rb +0 -140
  49. data/test/test_helper.rb +0 -79
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc516bb8bd2fd0f9fd310f848dbf272481d6c15a8ee3aeecba41ac8e24a7b8c3
4
- data.tar.gz: 2d79ba2d094e3694993f48e92565c7424121331aad653bd6cb5fad51a7f9ea75
3
+ metadata.gz: 799011b06831426c0ebecad641082d58bfaa8da0aea9359a3a2d152ea01bd196
4
+ data.tar.gz: eec3804031490d2382f59ddc450af14f73b696b9e14f0d2919b64a3df3557853
5
5
  SHA512:
6
- metadata.gz: 2d521a088a674f96b3639d624de7ababb6dbea93965fee1185b6a14f8a289ef88566a87cc5918004d3765f19de7ea0a15d99cfb30792ff519e1d8426555bb162
7
- data.tar.gz: 0a79e0832ce26282bacb13d534dde0460f33b677e7a07c23bde4d530848228bda65460ce2c229a97ddc25c5f12cc0aa75ea176f09e3959fcbf78e34536fa6bcd
6
+ metadata.gz: eab6dc676f7c5806bcd09f9adf87e5b67dd5320e043c07370014fdfc8e5ca1dffbaa9583754ac74bc354a30c6b27392c3310a7172b20699d475d9122e9dae748
7
+ data.tar.gz: b776c9d833e7808c7b2ac17ec6bb5a358a93cb1bb925ee94199aeddf85c0cca2e102cdcdfff17ca8d17ac406e0f76c4b981b640085fbd02d2868bca36fdd840d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,64 @@
1
1
  # Changelog
2
2
 
3
+ Notable changes to this project will be documented in this file.
4
+
5
+ This project adheres to [Semantic Versioning 2.0.0][1].
6
+
7
+ This document is formatted based on [Keep A CHANGELOG][2].
8
+
9
+ ## 1.8.0 / 2021-05-18
10
+
11
+ ### Changes
12
+
13
+ * Drop support for Ruby 2.4 ([2cf6b4050] and [#145])
14
+ * Update RubyParser compatibility target to 3.15.0 ([#105])
15
+ * Fix handling of dedented heredoc ([#106])
16
+ * Add support for running on Ruby 3.0 ([#123])
17
+ * Various code improvements and other internal changes
18
+
19
+ ## 1.7.2 / 2020-02-28
20
+
21
+ ### Bug fixes
22
+
23
+ * Support imaginary number literals ([#100])
24
+ * Handle anonymous kwrest arguments ([#95])
25
+
26
+ ### Internal changes
27
+
28
+ * Update tests ([#101])
29
+ * Prepare for testing on Ruby 2.7 ([#99])
30
+ * Various improvements ([#98])
31
+ * Split long module ([#97])
32
+
33
+ ## 1.7.1 / 2019-11-03
34
+
35
+ * Handle unicode escapes with five or six hex digits ([#94])
36
+ * Handle safe attribute assignment ([#92])
37
+ * Handle endless ranges on Ruby 2.6+ ([#90])
38
+ * Add preliminary support for Ruby 2.7 ([#89])
39
+ * Improve line number handling for stabby lambdas ([#88])
40
+
41
+ ## 1.7.0 / 2019-11-01
42
+
43
+ * Make results compatible with RubyParser 3.14.0 ([#85])
44
+ - Remove obsolete extra-compatible behavior
45
+ - Parse stabby lambda as :lambda-typed sexp
46
+ - Emit nil argument for block arguments with trailing comma
47
+ * Require Ruby 2.4 or higher ([#86])
48
+
49
+ ## 1.6.1 / 2019-04-22
50
+
51
+ * Improve line numbering for some block structures ([#82])
52
+ - Fix line numbering for empty method bodies
53
+ - Assign correct line numbers to END blocks
54
+ - Assign correct line numbers to begin blocks
55
+ - Assign correct line numbers to BEGIN blocks
56
+ * Fix line numbering for several literals ([#80])
57
+ - Fix line numbering for plain regexp literals
58
+ - Fix line numbering for backtick literals
59
+ - Fix line numbering for simple string literals
60
+ - Fix line numbering for keyword-like symbols
61
+
3
62
  ## 1.6.0 / 2019-04-12
4
63
 
5
64
  * Fix line numbering for range literals ([#79])
@@ -158,6 +217,25 @@
158
217
  * Initial release
159
218
 
160
219
  <!-- Pull request links -->
220
+ [#145]: https://github.com/mvz/ripper_ruby_parser/pull/145
221
+ [#123]: https://github.com/mvz/ripper_ruby_parser/pull/123
222
+ [#106]: https://github.com/mvz/ripper_ruby_parser/pull/106
223
+ [#105]: https://github.com/mvz/ripper_ruby_parser/pull/105
224
+ [#101]: https://github.com/mvz/ripper_ruby_parser/pull/101
225
+ [#100]: https://github.com/mvz/ripper_ruby_parser/pull/100
226
+ [#99]: https://github.com/mvz/ripper_ruby_parser/pull/99
227
+ [#98]: https://github.com/mvz/ripper_ruby_parser/pull/98
228
+ [#97]: https://github.com/mvz/ripper_ruby_parser/pull/97
229
+ [#95]: https://github.com/mvz/ripper_ruby_parser/pull/95
230
+ [#94]: https://github.com/mvz/ripper_ruby_parser/pull/94
231
+ [#92]: https://github.com/mvz/ripper_ruby_parser/pull/92
232
+ [#90]: https://github.com/mvz/ripper_ruby_parser/pull/90
233
+ [#89]: https://github.com/mvz/ripper_ruby_parser/pull/89
234
+ [#88]: https://github.com/mvz/ripper_ruby_parser/pull/88
235
+ [#86]: https://github.com/mvz/ripper_ruby_parser/pull/86
236
+ [#85]: https://github.com/mvz/ripper_ruby_parser/pull/85
237
+ [#82]: https://github.com/mvz/ripper_ruby_parser/pull/82
238
+ [#80]: https://github.com/mvz/ripper_ruby_parser/pull/80
161
239
  [#79]: https://github.com/mvz/ripper_ruby_parser/pull/79
162
240
  [#78]: https://github.com/mvz/ripper_ruby_parser/pull/78
163
241
  [#77]: https://github.com/mvz/ripper_ruby_parser/pull/77
@@ -173,3 +251,11 @@
173
251
  [#67]: https://github.com/mvz/ripper_ruby_parser/pull/67
174
252
  [#66]: https://github.com/mvz/ripper_ruby_parser/pull/66
175
253
  [#65]: https://github.com/mvz/ripper_ruby_parser/pull/65
254
+
255
+ <!-- Git sha links -->
256
+ [2cf6b4050]: https://github.com/mvz/ripper_ruby_parser/commit/2cf6b40501576003b916196e23222276b51aa53c
257
+
258
+ <!-- Other links -->
259
+
260
+ [1]: https://semver.org/spec/v2.0.0.html
261
+ [2]: https://keepachangelog.com/en/1.0.0/
data/README.md CHANGED
@@ -10,28 +10,18 @@ Parse with Ripper, produce sexps that are compatible with RubyParser.
10
10
 
11
11
  * Drop-in replacement for RubyParser
12
12
  * Should handle 1.9 and later syntax gracefully
13
- * Requires MRI 2.3 or higher
14
- * Compatible with RubyParser 3.13.1
13
+ * Requires Ruby 2.5 or higher
14
+ * Compatible with RubyParser 3.15.0
15
15
 
16
16
  ## Known incompatibilities
17
17
 
18
- RipperRubyParser has some incompatibilities with RubyParser. For some of these,
19
- the behavior can be changed by turning on extra-compatible mode.
20
-
21
- The following incompatibilities cannot be changed:
18
+ RipperRubyParser has a few incompatibilities with RubyParser.
22
19
 
23
20
  * RipperRubyParser won't handle non-UTF-8 files without an encoding comment,
24
21
  just like regular Ruby
25
- * RipperRubyParser does not attempt to match RubyParser's line numbering bugs
26
- * RipperRubyParser correctly dedents heredocs with interpolations
27
-
28
- The following incompatibilities can be made compatible by turning on
29
- extra-compatible mode:
30
-
31
- * Operator assignment of a method call without parentheses to a collection
32
- element uses and `:array` S-expression instead of `:arglist`
33
- * RipperRubyParser keeps carriage return characters in heredocs that include
34
- them
22
+ * RipperRubyParser does not always match RubyParser's line numbering
23
+ * RipperRubyParser dedents auto-dedenting heredocs
24
+ * RipperRubyParser does not include postfix comments
35
25
 
36
26
  ## Install
37
27
 
@@ -50,18 +40,11 @@ parser.parse "foo[bar] += baz qux"
50
40
  # s(:arglist, s(:call, nil, :bar)),
51
41
  # :+,
52
42
  # s(:call, nil, :baz, s(:call, nil, :qux)))
53
- parser.extra_compatible = true
54
-
55
- parser.parse "foo[bar] += baz qux"
56
- # => s(:op_asgn1, s(:call, nil, :foo),
57
- # s(:array, s(:call, nil, :bar)),
58
- # :+,
59
- # s(:call, nil, :baz, s(:call, nil, :qux)))
60
43
  ```
61
44
 
62
45
  ## Requirements
63
46
 
64
- * Ruby 2.3 or higher
47
+ * Ruby 2.5 or higher
65
48
  * `sexp_processor`
66
49
 
67
50
  ## Hacking and contributing
@@ -81,7 +64,7 @@ If you want to send pull requests or patches, please:
81
64
 
82
65
  (The MIT License)
83
66
 
84
- Copyright (c) 2012, 2014-2019 Matijs van Zuijlen
67
+ Copyright (c) 2012, 2014-2020 Matijs van Zuijlen
85
68
 
86
69
  Permission is hereby granted, free of charge, to any person obtaining
87
70
  a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ripper_ruby_parser/version'
4
- require 'ripper_ruby_parser/parser'
3
+ require "ripper_ruby_parser/version"
4
+ require "ripper_ruby_parser/parser"
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ripper'
4
- require 'ripper_ruby_parser/syntax_error'
5
- require 'ripper_ruby_parser/unescape'
3
+ require "ripper"
4
+ require "ripper_ruby_parser/syntax_error"
5
+ require "ripper_ruby_parser/unescape"
6
6
 
7
7
  module RipperRubyParser
8
8
  # Variant of Ripper's SexpBuilder parser class that inserts comments as
@@ -12,7 +12,7 @@ module RipperRubyParser
12
12
  class CommentingRipperParser < Ripper::SexpBuilder
13
13
  def initialize(*args)
14
14
  super
15
- @comment = ''
15
+ @comment = ""
16
16
  @comment_stack = []
17
17
  @delimiter_stack = []
18
18
  @space_before = false
@@ -22,16 +22,27 @@ module RipperRubyParser
22
22
 
23
23
  def parse
24
24
  result = super
25
- raise 'Ripper parse failed.' unless result
25
+ raise "Ripper parse failed." unless result
26
26
 
27
27
  Sexp.from_array(result)
28
28
  end
29
29
 
30
+ private
31
+
30
32
  def on_backtick(delimiter)
31
33
  @delimiter_stack.push delimiter
32
34
  super
33
35
  end
34
36
 
37
+ def on_begin(*args)
38
+ commentize(:begin, super)
39
+ end
40
+
41
+ def on_void_stmt
42
+ result = super
43
+ result << [lineno, column]
44
+ end
45
+
35
46
  def on_comment(tok)
36
47
  @comment += tok
37
48
  end
@@ -49,14 +60,15 @@ module RipperRubyParser
49
60
  end
50
61
 
51
62
  def on_kw(tok)
63
+ result = super
52
64
  case tok
53
- when 'class', 'def', 'module'
65
+ when "class", "def", "module", "BEGIN", "begin", "END"
54
66
  unless @in_symbol
55
- @comment_stack.push [tok.to_sym, @comment]
56
- @comment = ''
67
+ @comment_stack.push [result, @comment]
68
+ @comment = ""
57
69
  end
58
70
  end
59
- super
71
+ result
60
72
  end
61
73
 
62
74
  def on_module(*args)
@@ -91,6 +103,18 @@ module RipperRubyParser
91
103
  @delimiter_stack.push delimiter
92
104
  end
93
105
 
106
+ def on_heredoc_dedent(val, width)
107
+ next_dedent = true
108
+ val.map! do |e|
109
+ if e.is_a?(Array) && e[0] == :@tstring_content
110
+ e = dedent_element(e, width) if next_dedent
111
+ next_dedent = e[1].end_with? "\n"
112
+ end
113
+ e
114
+ end
115
+ val
116
+ end
117
+
94
118
  def on_heredoc_end(_delimiter)
95
119
  @delimiter_stack.pop
96
120
  end
@@ -245,7 +269,7 @@ module RipperRubyParser
245
269
  def on_unary(operator, value)
246
270
  if !@space_before && operator == :-@ && NUMBER_LITERAL_TYPES.include?(value.first)
247
271
  type, literal, lines = value
248
- if literal[0] == '-'
272
+ if literal[0] == "-"
249
273
  super
250
274
  else
251
275
  [type, "-#{literal}", lines]
@@ -275,31 +299,38 @@ module RipperRubyParser
275
299
  super
276
300
  end
277
301
 
278
- def on_parse_error(*args)
279
- raise SyntaxError, *args
302
+ def on_BEGIN(*args)
303
+ commentize(:BEGIN, super)
280
304
  end
281
305
 
282
- def on_class_name_error(*args)
283
- raise SyntaxError, *args
306
+ def on_END(*args)
307
+ commentize(:END, super)
284
308
  end
285
309
 
286
- def on_alias_error(*args)
287
- raise SyntaxError, *args
310
+ def on_parse_error(message)
311
+ raise SyntaxError, message
288
312
  end
289
313
 
290
- def on_assign_error(*args)
291
- raise SyntaxError, *args
314
+ def on_class_name_error(message, *)
315
+ raise SyntaxError, message
292
316
  end
293
317
 
294
- def on_param_error(*args)
295
- raise SyntaxError, *args
318
+ def on_alias_error(message, *)
319
+ raise SyntaxError, message
296
320
  end
297
321
 
298
- private
322
+ def on_assign_error(message, *)
323
+ raise SyntaxError, message
324
+ end
325
+
326
+ def on_param_error(message, *)
327
+ raise SyntaxError, message
328
+ end
299
329
 
300
330
  def commentize(_name, exp)
301
- _tok, comment = @comment_stack.pop
302
- @comment = ''
331
+ (_, _kw, loc), comment = @comment_stack.pop
332
+ @comment = ""
333
+ exp.push loc
303
334
  [:comment, comment, exp]
304
335
  end
305
336
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ripper_ruby_parser/commenting_ripper_parser'
4
- require 'ripper_ruby_parser/sexp_processor'
3
+ require "ripper_ruby_parser/commenting_ripper_parser"
4
+ require "ripper_ruby_parser/sexp_processor"
5
5
 
6
6
  module RipperRubyParser
7
7
  # Main parser class. Brings together Ripper and our
@@ -13,7 +13,7 @@ module RipperRubyParser
13
13
  @extra_compatible = false
14
14
  end
15
15
 
16
- def parse(source, filename = '(string)', lineno = 1)
16
+ def parse(source, filename = "(string)", lineno = 1)
17
17
  parser = CommentingRipperParser.new(source, filename, lineno)
18
18
  exp = parser.parse
19
19
 
@@ -1,15 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ripper_ruby_parser/sexp_handlers/helper_methods'
3
+ require "ripper_ruby_parser/sexp_handlers/helper_methods"
4
4
 
5
- require 'ripper_ruby_parser/sexp_handlers/assignment'
6
- require 'ripper_ruby_parser/sexp_handlers/blocks'
7
- require 'ripper_ruby_parser/sexp_handlers/conditionals'
8
- require 'ripper_ruby_parser/sexp_handlers/literals'
9
- require 'ripper_ruby_parser/sexp_handlers/loops'
10
- require 'ripper_ruby_parser/sexp_handlers/method_calls'
11
- require 'ripper_ruby_parser/sexp_handlers/methods'
12
- require 'ripper_ruby_parser/sexp_handlers/operators'
5
+ require "ripper_ruby_parser/sexp_handlers/assignment"
6
+ require "ripper_ruby_parser/sexp_handlers/blocks"
7
+ require "ripper_ruby_parser/sexp_handlers/conditionals"
8
+ require "ripper_ruby_parser/sexp_handlers/literals"
9
+ require "ripper_ruby_parser/sexp_handlers/loops"
10
+ require "ripper_ruby_parser/sexp_handlers/method_calls"
11
+ require "ripper_ruby_parser/sexp_handlers/methods"
12
+ require "ripper_ruby_parser/sexp_handlers/operators"
13
+ require "ripper_ruby_parser/sexp_handlers/string_literals"
13
14
 
14
15
  module RipperRubyParser
15
16
  # Umbrella module for handlers of particular sexp types
@@ -28,6 +29,7 @@ module RipperRubyParser
28
29
  include MethodCalls
29
30
  include Methods
30
31
  include Operators
32
+ include StringLiterals
31
33
  end
32
34
  end
33
35
  end
@@ -96,11 +96,10 @@ module RipperRubyParser
96
96
  _, lvalue, (_, operator,), value = exp.shift 4
97
97
 
98
98
  lvalue = process(lvalue)
99
- original_value_type = value.sexp_type
100
99
  value = process(value)
101
100
  operator = operator.chop.to_sym
102
101
 
103
- create_operator_assignment_sub_type lvalue, value, operator, original_value_type
102
+ create_operator_assignment_sub_type lvalue, value, operator
104
103
  end
105
104
 
106
105
  private
@@ -123,16 +122,11 @@ module RipperRubyParser
123
122
  '&&': :op_asgn_and
124
123
  }.freeze
125
124
 
126
- def create_operator_assignment_sub_type(lvalue, value, operator, original_value_type)
125
+ def create_operator_assignment_sub_type(lvalue, value, operator)
127
126
  case lvalue.sexp_type
128
127
  when :aref_field
129
128
  _, arr, arglist = lvalue
130
- arglist.sexp_type = if extra_compatible &&
131
- [:command, :command_call].include?(original_value_type)
132
- :array
133
- else
134
- :arglist
135
- end
129
+ arglist.sexp_type = :arglist
136
130
  s(:op_asgn1, arr, arglist, operator, value)
137
131
  when :field
138
132
  _, obj, _, (_, field) = lvalue
@@ -156,8 +150,13 @@ module RipperRubyParser
156
150
  arglist.shift
157
151
  s(:attrasgn, arr, :[]=, *arglist)
158
152
  when :field
159
- _, obj, _, (_, field) = lvalue
160
- s(:attrasgn, obj, :"#{field}=", value)
153
+ _, obj, call_op, (_, field) = lvalue
154
+ case call_op
155
+ when :"&.", s(:op, :"&.") # Handle both 2.5 and 2.6 style ops
156
+ s(:safe_attrasgn, obj, :"#{field}=", value)
157
+ else
158
+ s(:attrasgn, obj, :"#{field}=", value)
159
+ end
161
160
  else
162
161
  create_assignment_sub_type lvalue, value
163
162
  end
@@ -17,13 +17,14 @@ module RipperRubyParser
17
17
  def process_params(exp)
18
18
  _, normal, defaults, splat, rest, kwargs, doublesplat, block = exp.shift 8
19
19
 
20
- args = handle_normal_arguments normal
21
- args += handle_default_arguments defaults
22
- args += handle_splat splat
23
- args += handle_normal_arguments rest
24
- args += handle_kwargs kwargs
25
- args += handle_double_splat doublesplat
26
- args += handle_block_argument block
20
+ args =
21
+ handle_normal_arguments(normal) +
22
+ handle_default_arguments(defaults) +
23
+ handle_splat(splat) +
24
+ handle_normal_arguments(rest) +
25
+ handle_kwargs(kwargs) +
26
+ handle_double_splat(doublesplat) +
27
+ handle_block_argument(block)
27
28
 
28
29
  s(:args, *args)
29
30
  end
@@ -35,7 +36,7 @@ module RipperRubyParser
35
36
 
36
37
  def process_kwrest_param(exp)
37
38
  _, sym, = exp.shift 3
38
- process(sym)
39
+ process(sym) || s(:lvar, :"")
39
40
  end
40
41
 
41
42
  def process_block_var(exp)
@@ -47,10 +48,10 @@ module RipperRubyParser
47
48
  end
48
49
 
49
50
  def process_begin(exp)
50
- _, body = exp.shift 2
51
+ _, body, pos = exp.shift 3
51
52
 
52
- body = convert_empty_to_nil_symbol process(body)
53
- s(:begin, body)
53
+ body = convert_void_stmt_to_nil_symbol process(body)
54
+ with_position pos, s(:begin, body)
54
55
  end
55
56
 
56
57
  def process_rescue(exp)
@@ -58,51 +59,32 @@ module RipperRubyParser
58
59
  rescue_block = map_process_list_compact block.sexp_body
59
60
  rescue_block << nil if rescue_block.empty?
60
61
 
61
- capture = if eclass
62
- if eclass.first.is_a? Symbol
63
- eclass = process(eclass)
64
- body = eclass.sexp_body
65
- if eclass.sexp_type == :mrhs
66
- body.first
67
- else
68
- s(:array, *body)
69
- end
70
- else
71
- s(:array, process(eclass.first))
72
- end
73
- else
74
- s(:array)
75
- end
62
+ capture = handle_rescue_class_list eclass
76
63
 
77
64
  capture << create_assignment_sub_type(process(evar), s(:gvar, :$!)) if evar
78
65
 
79
- s(
80
- s(:resbody, capture, *rescue_block),
81
- *process(after))
66
+ s(s(:resbody, capture, *rescue_block), *process(after))
82
67
  end
83
68
 
84
69
  def process_bodystmt(exp)
85
70
  _, main, rescue_block, else_block, ensure_block = exp.shift 5
86
71
 
87
- body = s()
72
+ body_list = []
88
73
 
89
- main = wrap_in_block map_process_list_compact main.sexp_body
90
- body << main if main
74
+ main_block = process(main)
75
+ line = main_block.line
76
+ body_list << main_block if main_block.sexp_type != :void_stmt
91
77
 
92
- if rescue_block
93
- body.push(*process(rescue_block))
94
- body << process(else_block) if else_block
95
- body = s(s(:rescue, *body))
96
- elsif else_block
97
- body << process(else_block)
98
- end
78
+ body_list.push(*process(rescue_block)) if rescue_block
79
+ body_list << process(else_block) if else_block
80
+ body_list = [s(:rescue, *body_list)] if rescue_block
99
81
 
100
82
  if ensure_block
101
- body << process(ensure_block)
102
- body = s(s(:ensure, *body))
83
+ body_list << process(ensure_block)
84
+ body_list = [s(:ensure, *body_list)]
103
85
  end
104
86
 
105
- wrap_in_block(body) || s()
87
+ wrap_in_block(body_list, line)
106
88
  end
107
89
 
108
90
  def process_rescue_mod(exp)
@@ -138,12 +120,16 @@ module RipperRubyParser
138
120
 
139
121
  def process_lambda(exp)
140
122
  _, args, statements = exp.shift 3
123
+
141
124
  old_type = args.sexp_type
142
125
  args = convert_arguments(process(args))
126
+ statements = process(statements)
127
+ line = args.line || statements.line
143
128
  args = nil if args == s(:args) && old_type == :params
144
- make_iter(s(:call, nil, :lambda),
145
- args,
146
- safe_unwrap_void_stmt(process(statements)))
129
+ call = s(:lambda)
130
+ call.line = line
131
+
132
+ make_iter call, args, safe_unwrap_void_stmt(statements)
147
133
  end
148
134
 
149
135
  private
@@ -165,7 +151,10 @@ module RipperRubyParser
165
151
  end
166
152
 
167
153
  def handle_splat(splat)
168
- if splat && splat != 0
154
+ if splat == 0
155
+ # Only relevant for Ruby < 2.6
156
+ [s(:excessed_comma)]
157
+ elsif splat
169
158
  [process(splat)]
170
159
  else
171
160
  []
@@ -197,17 +186,24 @@ module RipperRubyParser
197
186
  [process(block)]
198
187
  end
199
188
 
200
- def convert_empty_to_nil_symbol(block)
201
- case block.length
202
- when 0
203
- s(:nil)
189
+ def handle_rescue_class_list(eclass)
190
+ if eclass.nil?
191
+ s(:array)
192
+ elsif eclass.first.is_a? Symbol
193
+ eclass = process(eclass)
194
+ body = eclass.sexp_body
195
+ if eclass.sexp_type == :mrhs
196
+ body.first
197
+ else
198
+ s(:array, *body)
199
+ end
204
200
  else
205
- block
201
+ s(:array, process(eclass.first))
206
202
  end
207
203
  end
208
204
 
209
205
  def make_iter(call, args, stmt)
210
- args.pop if args && args.last == s(:excessed_comma)
206
+ args[-1] = nil if args && args.last == s(:excessed_comma)
211
207
  args ||= 0
212
208
  if stmt.empty?
213
209
  s(:iter, call, args)
@@ -215,17 +211,6 @@ module RipperRubyParser
215
211
  s(:iter, call, args, stmt)
216
212
  end
217
213
  end
218
-
219
- def wrap_in_block(statements)
220
- case statements.length
221
- when 0
222
- nil
223
- when 1
224
- statements.first
225
- else
226
- s(:block, *statements)
227
- end
228
- end
229
214
  end
230
215
  end
231
216
  end