ripper_ruby_parser 0.0.8 → 1.0.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 (31) hide show
  1. checksums.yaml +7 -0
  2. data/{README.rdoc → README.md} +17 -17
  3. data/Rakefile +3 -1
  4. data/lib/ripper_ruby_parser/{commenting_sexp_builder.rb → commenting_ripper_parser.rb} +22 -6
  5. data/lib/ripper_ruby_parser/parser.rb +3 -18
  6. data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +2 -1
  7. data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +6 -10
  8. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +37 -60
  9. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +31 -25
  10. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +18 -8
  11. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +22 -18
  12. data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +12 -23
  13. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +16 -8
  14. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +41 -15
  15. data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +40 -23
  16. data/lib/ripper_ruby_parser/sexp_processor.rb +38 -19
  17. data/lib/ripper_ruby_parser/version.rb +1 -1
  18. data/test/pt_testcase/pt_test.rb +15 -1
  19. data/test/test_helper.rb +6 -3
  20. data/test/unit/commenting_ripper_parser_test.rb +121 -0
  21. data/test/unit/parser_assignment_test.rb +23 -24
  22. data/test/unit/parser_blocks_test.rb +207 -35
  23. data/test/unit/parser_conditionals_test.rb +251 -9
  24. data/test/unit/parser_literals_test.rb +348 -8
  25. data/test/unit/parser_loops_test.rb +20 -21
  26. data/test/unit/parser_method_calls_test.rb +132 -8
  27. data/test/unit/parser_operators_test.rb +97 -7
  28. data/test/unit/parser_test.rb +631 -1231
  29. data/test/unit/sexp_processor_test.rb +26 -28
  30. metadata +28 -38
  31. data/test/unit/commenting_sexp_builder_test.rb +0 -113
@@ -49,14 +49,14 @@ module RipperRubyParser
49
49
  _, content = exp.shift 2
50
50
 
51
51
  statements = content.map { |sub_exp| process(sub_exp) }
52
- wrap_in_block statements
52
+ safe_wrap_in_block statements
53
53
  end
54
54
 
55
55
  def process_module exp
56
56
  _, const_ref, body = exp.shift 3
57
57
  const, line = const_ref_to_const_with_line_number const_ref
58
58
  with_line_number(line,
59
- s(:module, const, class_or_module_body(body)))
59
+ s(:module, const, *class_or_module_body(body)))
60
60
  end
61
61
 
62
62
  def process_class exp
@@ -64,12 +64,12 @@ module RipperRubyParser
64
64
  const, line = const_ref_to_const_with_line_number const_ref
65
65
  parent = process(parent)
66
66
  with_line_number(line,
67
- s(:class, const, parent, class_or_module_body(body)))
67
+ s(:class, const, parent, *class_or_module_body(body)))
68
68
  end
69
69
 
70
70
  def process_sclass exp
71
71
  _, klass, block = exp.shift 3
72
- s(:sclass, process(klass), class_or_module_body(block))
72
+ s(:sclass, process(klass), *class_or_module_body(block))
73
73
  end
74
74
 
75
75
  def process_var_ref exp
@@ -82,6 +82,11 @@ module RipperRubyParser
82
82
  process(contents)
83
83
  end
84
84
 
85
+ def process_var_alias exp
86
+ _, left, right = exp.shift 3
87
+ s(:valias, left[1].to_sym, right[1].to_sym)
88
+ end
89
+
85
90
  def process_const_path_ref exp
86
91
  _, left, right = exp.shift 3
87
92
  s(:colon2, process(left), extract_node_symbol(right))
@@ -112,7 +117,8 @@ module RipperRubyParser
112
117
  elsif body.first.is_a? Symbol
113
118
  process body
114
119
  else
115
- process body[0]
120
+ body.map! {|it| convert_void_stmt_to_nil process it }
121
+ safe_wrap_in_block body
116
122
  end
117
123
  end
118
124
 
@@ -123,6 +129,16 @@ module RipperRubyParser
123
129
  sexp
124
130
  end
125
131
 
132
+ def process_BEGIN exp
133
+ _, body = exp.shift 2
134
+ s(:iter, s(:preexe), s(:args), *map_body(body))
135
+ end
136
+
137
+ def process_END exp
138
+ _, body = exp.shift 2
139
+ s(:iter, s(:postexe), s(:args), *map_body(body))
140
+ end
141
+
126
142
  # number literals
127
143
  def process_at_int exp
128
144
  make_literal(exp) {|val| Integer(val) }
@@ -134,13 +150,8 @@ module RipperRubyParser
134
150
 
135
151
  # character literals
136
152
  def process_at_CHAR exp
137
- make_literal(exp) do |val|
138
- if extra_compatible
139
- val[1].ord
140
- else
141
- val[1]
142
- end
143
- end
153
+ _, val, pos = exp.shift 3
154
+ with_position(pos, s(:str, unescape(val[1..-1])))
144
155
  end
145
156
 
146
157
  def process_at_label exp
@@ -209,14 +220,14 @@ module RipperRubyParser
209
220
  end
210
221
 
211
222
  def class_or_module_body exp
212
- scope = process exp
213
- block = scope[1]
214
- block.shift
215
- if block.length <= 1
216
- s(:scope, *block)
217
- else
218
- s(:scope, s(:block, *block))
223
+ body = process(exp)
224
+
225
+ if body.length == 1 && body.first.sexp_type == :block
226
+ body = body.first
227
+ body.shift
219
228
  end
229
+
230
+ body
220
231
  end
221
232
 
222
233
  def make_identifier(type, exp)
@@ -246,5 +257,13 @@ module RipperRubyParser
246
257
  end
247
258
  end
248
259
  end
260
+
261
+ def convert_void_stmt_to_nil sexp
262
+ if sexp == s(:void_stmt)
263
+ s(:nil)
264
+ else
265
+ sexp
266
+ end
267
+ end
249
268
  end
250
269
  end
@@ -1,3 +1,3 @@
1
1
  module RipperRubyParser
2
- VERSION = '0.0.8'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -7,13 +7,27 @@ class RipperRubyParser::Parser
7
7
  end
8
8
  end
9
9
 
10
+ SKIPPED_TESTS = ["dstr_heredoc_windoze_sucks"]
11
+
10
12
  class RubyParserTestCase < ParseTreeTestCase
11
13
  def self.previous key
12
14
  "Ruby"
13
15
  end
14
16
 
15
17
  def self.generate_test klass, node, data, input_name, output_name
16
- return if Array === data['Ruby']
18
+ if data['Ruby'].is_a? Array
19
+ klass.send :define_method, "test_#{node}" do
20
+ skip "Not a parser test"
21
+ end
22
+ return
23
+ end
24
+
25
+ if SKIPPED_TESTS.include? node
26
+ klass.send :define_method, "test_#{node}" do
27
+ skip "Can't or won't fix this difference"
28
+ end
29
+ return
30
+ end
17
31
 
18
32
  output_name = "ParseTree"
19
33
 
data/test/test_helper.rb CHANGED
@@ -1,8 +1,11 @@
1
- if ENV["SIMPLECOV"]
1
+ begin
2
2
  require 'simplecov'
3
- SimpleCov.start
3
+ SimpleCov.start do
4
+ add_filter "/test/"
5
+ end
6
+ rescue LoadError
4
7
  end
5
- require 'minitest/spec'
8
+
6
9
  require 'minitest/autorun'
7
10
 
8
11
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
@@ -0,0 +1,121 @@
1
+ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe RipperRubyParser::CommentingRipperParser do
4
+ def parse_with_builder str
5
+ builder = RipperRubyParser::CommentingRipperParser.new str
6
+ builder.parse
7
+ end
8
+
9
+ def empty_params_list
10
+ @empty_params_list ||= begin
11
+ num_params = RUBY_VERSION < "2.0.0" ? 5 : 7
12
+ s(:params, *([nil] * num_params))
13
+ end
14
+
15
+ end
16
+
17
+ describe "handling comments" do
18
+ it "produces a comment node surrounding a commented def" do
19
+ result = parse_with_builder "# Foo\ndef foo; end"
20
+ result.must_equal s(:program,
21
+ s(s(:comment,
22
+ "# Foo\n",
23
+ s(:def,
24
+ s(:@ident, "foo", s(2, 4)),
25
+ empty_params_list,
26
+ s(:bodystmt, s(s(:void_stmt)), nil, nil, nil)))))
27
+ end
28
+
29
+ it "produces a blank comment node surrounding a def that has no comment" do
30
+ result = parse_with_builder "def foo; end"
31
+ result.must_equal s(:program,
32
+ s(s(:comment,
33
+ "",
34
+ s(:def,
35
+ s(:@ident, "foo", s(1, 4)),
36
+ empty_params_list,
37
+ s(:bodystmt, s(s(:void_stmt)), nil, nil, nil)))))
38
+ end
39
+
40
+ it "produces a comment node surrounding a commented class" do
41
+ result = parse_with_builder "# Foo\nclass Foo; end"
42
+ result.must_equal s(:program,
43
+ s(s(:comment,
44
+ "# Foo\n",
45
+ s(:class,
46
+ s(:const_ref, s(:@const, "Foo", s(2, 6))),
47
+ nil,
48
+ s(:bodystmt, s(s(:void_stmt)), nil, nil, nil)))))
49
+ end
50
+
51
+ it "produce a blank comment node surrounding a class that has no comment" do
52
+ result = parse_with_builder "class Foo; end"
53
+ result.must_equal s(:program,
54
+ s(s(:comment,
55
+ "",
56
+ s(:class,
57
+ s(:const_ref, s(:@const, "Foo", s(1, 6))),
58
+ nil,
59
+ s(:bodystmt, s(s(:void_stmt)), nil, nil, nil)))))
60
+ end
61
+
62
+ it "produces a comment node surrounding a commented module" do
63
+ result = parse_with_builder "# Foo\nmodule Foo; end"
64
+ result.must_equal s(:program,
65
+ s(s(:comment,
66
+ "# Foo\n",
67
+ s(:module,
68
+ s(:const_ref, s(:@const, "Foo", s(2, 7))),
69
+ s(:bodystmt, s(s(:void_stmt)), nil, nil, nil)))))
70
+ end
71
+
72
+ it "produces a blank comment node surrounding a module that has no comment" do
73
+ result = parse_with_builder "module Foo; end"
74
+ result.must_equal s(:program,
75
+ s(s(:comment,
76
+ "",
77
+ s(:module,
78
+ s(:const_ref, s(:@const, "Foo", s(1, 7))),
79
+ s(:bodystmt, s(s(:void_stmt)), nil, nil, nil)))))
80
+ end
81
+
82
+ it "is not confused by a symbol containing a keyword" do
83
+ result = parse_with_builder ":class; def foo; end"
84
+ result.must_equal s(:program,
85
+ s(s(:symbol_literal, s(:symbol, s(:@kw, "class", s(1, 1)))),
86
+ s(:comment,
87
+ "",
88
+ s(:def,
89
+ s(:@ident, "foo", s(1, 12)),
90
+ empty_params_list,
91
+ s(:bodystmt, s(s(:void_stmt)), nil, nil, nil)))))
92
+ end
93
+
94
+ it "is not confused by a dynamic symbol" do
95
+ result = parse_with_builder ":'foo'; def bar; end"
96
+ result.must_equal s(:program,
97
+ s(s(:dyna_symbol, s(s(:@tstring_content, "foo", s(1, 2)))),
98
+ s(:comment,
99
+ "",
100
+ s(:def,
101
+ s(:@ident, "bar", s(1, 12)),
102
+ empty_params_list,
103
+ s(:bodystmt, s(s(:void_stmt)), nil, nil, nil)))))
104
+ end
105
+
106
+ it "is not confused by a dynamic symbol containing a class definition" do
107
+ result = parse_with_builder ":\"foo\#{class Bar;end}\""
108
+ result.must_equal s(:program,
109
+ s(s(:dyna_symbol,
110
+ s(s(:@tstring_content, "foo", s(1, 2)),
111
+ s(:string_embexpr,
112
+ s(s(:comment,
113
+ "",
114
+ s(:class,
115
+ s(:const_ref, s(:@const, "Bar", s(1, 13))),
116
+ nil,
117
+ s(:bodystmt, s(s(:void_stmt)), nil, nil, nil)))))))))
118
+ end
119
+ end
120
+ end
121
+
@@ -7,14 +7,14 @@ describe RipperRubyParser::Parser do
7
7
  "Foo::Bar = baz".
8
8
  must_be_parsed_as s(:cdecl,
9
9
  s(:colon2, s(:const, :Foo), :Bar),
10
- s(:call, nil, :baz, s(:arglist)))
10
+ s(:call, nil, :baz))
11
11
  end
12
12
 
13
13
  it "works when assigning to constant in the root namespace" do
14
14
  "::Foo = bar".
15
15
  must_be_parsed_as s(:cdecl,
16
16
  s(:colon3, :Foo),
17
- s(:call, nil, :bar, s(:arglist)))
17
+ s(:call, nil, :bar))
18
18
  end
19
19
 
20
20
  describe "with a right-hand splat" do
@@ -23,7 +23,7 @@ describe RipperRubyParser::Parser do
23
23
  must_be_parsed_as s(:lasgn, :foo,
24
24
  s(:svalue,
25
25
  s(:splat,
26
- s(:call, nil, :bar, s(:arglist)))))
26
+ s(:call, nil, :bar))))
27
27
  end
28
28
 
29
29
  specify do
@@ -31,9 +31,9 @@ describe RipperRubyParser::Parser do
31
31
  must_be_parsed_as s(:lasgn, :foo,
32
32
  s(:svalue,
33
33
  s(:array,
34
- s(:call, nil, :bar, s(:arglist)),
34
+ s(:call, nil, :bar),
35
35
  s(:splat,
36
- s(:call, nil, :baz, s(:arglist))))))
36
+ s(:call, nil, :baz)))))
37
37
  end
38
38
  end
39
39
 
@@ -43,8 +43,8 @@ describe RipperRubyParser::Parser do
43
43
  must_be_parsed_as s(:lasgn, :foo,
44
44
  s(:svalue,
45
45
  s(:array,
46
- s(:call, nil, :bar, s(:arglist)),
47
- s(:call, nil, :baz, s(:arglist)))))
46
+ s(:call, nil, :bar),
47
+ s(:call, nil, :baz))))
48
48
  end
49
49
  end
50
50
 
@@ -53,8 +53,8 @@ describe RipperRubyParser::Parser do
53
53
  "foo = [bar, baz]".
54
54
  must_be_parsed_as s(:lasgn, :foo,
55
55
  s(:array,
56
- s(:call, nil, :bar, s(:arglist)),
57
- s(:call, nil, :baz, s(:arglist))))
56
+ s(:call, nil, :bar),
57
+ s(:call, nil, :baz)))
58
58
  end
59
59
  end
60
60
  end
@@ -64,7 +64,7 @@ describe RipperRubyParser::Parser do
64
64
  "foo, * = bar".
65
65
  must_be_parsed_as s(:masgn,
66
66
  s(:array, s(:lasgn, :foo), s(:splat)),
67
- s(:to_ary, s(:call, nil, :bar, s(:arglist))))
67
+ s(:to_ary, s(:call, nil, :bar)))
68
68
  end
69
69
 
70
70
  specify do
@@ -73,7 +73,7 @@ describe RipperRubyParser::Parser do
73
73
  s(:array,
74
74
  s(:lasgn, :foo),
75
75
  s(:splat, s(:lasgn, :bar))),
76
- s(:to_ary, s(:call, nil, :baz, s(:arglist))))
76
+ s(:to_ary, s(:call, nil, :baz)))
77
77
  end
78
78
  end
79
79
 
@@ -81,12 +81,11 @@ describe RipperRubyParser::Parser do
81
81
  it "handles multiple indices" do
82
82
  "foo[bar, baz] = qux".
83
83
  must_be_parsed_as s(:attrasgn,
84
- s(:call, nil, :foo, s(:arglist)),
84
+ s(:call, nil, :foo),
85
85
  :[]=,
86
- s(:arglist,
87
- s(:call, nil, :bar, s(:arglist)),
88
- s(:call, nil, :baz, s(:arglist)),
89
- s(:call, nil, :qux, s(:arglist))))
86
+ s(:call, nil, :bar),
87
+ s(:call, nil, :baz),
88
+ s(:call, nil, :qux))
90
89
  end
91
90
  end
92
91
 
@@ -95,18 +94,18 @@ describe RipperRubyParser::Parser do
95
94
  it "handles multiple indices" do
96
95
  "foo[bar, baz] += qux".
97
96
  must_be_parsed_as s(:op_asgn1,
98
- s(:call, nil, :foo, s(:arglist)),
97
+ s(:call, nil, :foo),
99
98
  s(:arglist,
100
- s(:call, nil, :bar, s(:arglist)),
101
- s(:call, nil, :baz, s(:arglist))),
99
+ s(:call, nil, :bar),
100
+ s(:call, nil, :baz)),
102
101
  :+,
103
- s(:call, nil, :qux, s(:arglist)))
102
+ s(:call, nil, :qux))
104
103
  end
105
104
 
106
105
  it "works with &&=" do
107
106
  "foo &&= bar".
108
107
  must_be_parsed_as s(:op_asgn_and,
109
- s(:lvar, :foo), s(:lasgn, :foo, s(:call, nil, :bar, s(:arglist))))
108
+ s(:lvar, :foo), s(:lasgn, :foo, s(:call, nil, :bar)))
110
109
  end
111
110
  end
112
111
  end
@@ -117,15 +116,15 @@ describe RipperRubyParser::Parser do
117
116
  "foo, bar = *baz".
118
117
  must_be_parsed_as s(:masgn,
119
118
  s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
120
- s(:splat, s(:call, nil, :baz, s(:arglist))))
119
+ s(:splat, s(:call, nil, :baz)))
121
120
  end
122
121
  specify do
123
122
  "foo, bar = baz, *qux".
124
123
  must_be_parsed_as s(:masgn,
125
124
  s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
126
125
  s(:array,
127
- s(:call, nil, :baz, s(:arglist)),
128
- s(:splat, s(:call, nil, :qux, s(:arglist)))))
126
+ s(:call, nil, :baz),
127
+ s(:splat, s(:call, nil, :qux))))
129
128
  end
130
129
  end
131
130
  end
@@ -6,88 +6,252 @@ describe RipperRubyParser::Parser do
6
6
  specify do
7
7
  "foo do |(bar, baz)| end".
8
8
  must_be_parsed_as s(:iter,
9
- s(:call, nil, :foo, s(:arglist)),
10
- s(:masgn,
11
- s(:array,
12
- s(:lasgn, :bar),
13
- s(:lasgn, :baz))))
9
+ s(:call, nil, :foo),
10
+ s(:args,
11
+ s(:masgn, :bar, :baz)))
14
12
  end
15
13
 
16
14
  specify do
17
15
  "foo do |(bar, *baz)| end".
18
16
  must_be_parsed_as s(:iter,
19
- s(:call, nil, :foo, s(:arglist)),
20
- s(:masgn,
21
- s(:array,
22
- s(:lasgn, :bar),
23
- s(:splat, s(:lasgn, :baz)))))
17
+ s(:call, nil, :foo),
18
+ s(:args,
19
+ s(:masgn, :bar, :"*baz")))
24
20
  end
25
21
 
26
22
  specify do
27
23
  "foo do |bar,*| end".
28
24
  must_be_parsed_as s(:iter,
29
- s(:call, nil, :foo, s(:arglist)),
30
- s(:masgn, s(:array, s(:lasgn, :bar), s(:splat))))
25
+ s(:call, nil, :foo),
26
+ s(:args, :bar, :"*"))
31
27
  end
32
28
 
33
29
  specify do
34
30
  "foo do |bar, &baz| end".
35
31
  must_be_parsed_as s(:iter,
36
- s(:call, nil, :foo, s(:arglist)),
37
- s(:masgn,
38
- s(:array,
39
- s(:lasgn, :bar),
40
- s(:lasgn, :"&baz"))))
32
+ s(:call, nil, :foo),
33
+ s(:args, :bar, :"&baz"))
41
34
  end
42
35
 
43
- it "behaves differently from RubyParser with a trailing comma in the block parameters" do
36
+ it "handles empty parameter specs" do
37
+ "foo do ||; bar; end".
38
+ must_be_parsed_as s(:iter,
39
+ s(:call, nil, :foo),
40
+ 0,
41
+ s(:call, nil, :bar))
42
+ end
43
+
44
+ it "ignores a trailing comma in the block parameters" do
44
45
  "foo do |bar, | end".
45
46
  must_be_parsed_as s(:iter,
46
- s(:call, nil, :foo, s(:arglist)),
47
- s(:lasgn, :bar))
47
+ s(:call, nil, :foo),
48
+ s(:args, :bar))
48
49
  end
49
50
  end
50
51
 
51
- describe "for rescue/else/ensure" do
52
+ describe "for rescue/else" do
52
53
  it "works for a block with multiple rescue statements" do
53
54
  "begin foo; rescue; bar; rescue; baz; end".
54
55
  must_be_parsed_as s(:rescue,
55
- s(:call, nil, :foo, s(:arglist)),
56
+ s(:call, nil, :foo),
56
57
  s(:resbody,
57
58
  s(:array),
58
- s(:call, nil, :bar, s(:arglist))),
59
+ s(:call, nil, :bar)),
59
60
  s(:resbody,
60
61
  s(:array),
61
- s(:call, nil, :baz, s(:arglist))))
62
+ s(:call, nil, :baz)))
62
63
  end
63
64
 
64
65
  it "works for a block with rescue and else" do
65
66
  "begin; foo; rescue; bar; else; baz; end".
66
67
  must_be_parsed_as s(:rescue,
67
- s(:call, nil, :foo, s(:arglist)),
68
+ s(:call, nil, :foo),
68
69
  s(:resbody,
69
70
  s(:array),
70
- s(:call, nil, :bar, s(:arglist))),
71
- s(:call, nil, :baz, s(:arglist)))
71
+ s(:call, nil, :bar)),
72
+ s(:call, nil, :baz))
72
73
  end
73
74
 
74
75
  it "works for a block with only else" do
75
76
  "begin; foo; else; bar; end".
76
77
  must_be_parsed_as s(:block,
77
- s(:call, nil, :foo, s(:arglist)),
78
- s(:call, nil, :bar, s(:arglist)))
78
+ s(:call, nil, :foo),
79
+ s(:call, nil, :bar))
79
80
  end
80
81
  end
81
82
 
82
- describe "for rescue" do
83
+ describe "for the rescue statement" do
83
84
  it "works with assignment to an error variable" do
84
85
  "begin; foo; rescue => bar; baz; end".
85
86
  must_be_parsed_as s(:rescue,
86
- s(:call, nil, :foo, s(:arglist)),
87
+ s(:call, nil, :foo),
87
88
  s(:resbody,
88
89
  s(:array,
89
90
  s(:lasgn, :bar, s(:gvar, :$!))),
90
- s(:call, nil, :baz, s(:arglist))))
91
+ s(:call, nil, :baz)))
92
+ end
93
+
94
+ it "works with assignment of the exception to an instance variable" do
95
+ "begin; foo; rescue => @bar; baz; end".
96
+ must_be_parsed_as s(:rescue,
97
+ s(:call, nil, :foo),
98
+ s(:resbody,
99
+ s(:array,
100
+ s(:iasgn, :@bar, s(:gvar, :$!))),
101
+ s(:call, nil, :baz)))
102
+ end
103
+
104
+ it "works with empty main and rescue bodies" do
105
+ "begin; rescue; end".
106
+ must_be_parsed_as s(:rescue,
107
+ s(:resbody, s(:array), nil))
108
+ end
109
+
110
+ it "works with single statement main and rescue bodies" do
111
+ "begin; foo; rescue; bar; end".
112
+ must_be_parsed_as s(:rescue,
113
+ s(:call, nil, :foo),
114
+ s(:resbody,
115
+ s(:array),
116
+ s(:call, nil, :bar)))
117
+ end
118
+
119
+ it "works with multi-statement main and rescue bodies" do
120
+ "begin; foo; bar; rescue; baz; qux; end".
121
+ must_be_parsed_as s(:rescue,
122
+ s(:block,
123
+ s(:call, nil, :foo),
124
+ s(:call, nil, :bar)),
125
+ s(:resbody,
126
+ s(:array),
127
+ s(:call, nil, :baz),
128
+ s(:call, nil, :qux)))
129
+ end
130
+
131
+ it "works with assignment to an error variable" do
132
+ "begin; foo; rescue => e; bar; end".
133
+ must_be_parsed_as s(:rescue,
134
+ s(:call, nil, :foo),
135
+ s(:resbody,
136
+ s(:array, s(:lasgn, :e, s(:gvar, :$!))),
137
+ s(:call, nil, :bar)))
138
+ end
139
+
140
+ it "works with filtering of the exception type" do
141
+ "begin; foo; rescue Bar; baz; end".
142
+ must_be_parsed_as s(:rescue,
143
+ s(:call, nil, :foo),
144
+ s(:resbody,
145
+ s(:array, s(:const, :Bar)),
146
+ s(:call, nil, :baz)))
147
+ end
148
+
149
+ it "works with filtering of the exception type and assignment to an error variable" do
150
+ "begin; foo; rescue Bar => e; baz; end".
151
+ must_be_parsed_as s(:rescue,
152
+ s(:call, nil, :foo),
153
+ s(:resbody,
154
+ s(:array,
155
+ s(:const, :Bar),
156
+ s(:lasgn, :e, s(:gvar, :$!))),
157
+ s(:call, nil, :baz)))
158
+ end
159
+
160
+ it "works rescuing multiple exception types" do
161
+ "begin; foo; rescue Bar, Baz; qux; end".
162
+ must_be_parsed_as s(:rescue,
163
+ s(:call, nil, :foo),
164
+ s(:resbody,
165
+ s(:array, s(:const, :Bar), s(:const, :Baz)),
166
+ s(:call, nil, :qux)))
167
+ end
168
+
169
+ it "works in the postfix case" do
170
+ "foo rescue bar".
171
+ must_be_parsed_as s(:rescue,
172
+ s(:call, nil, :foo),
173
+ s(:resbody,
174
+ s(:array),
175
+ s(:call, nil, :bar)))
176
+ end
177
+
178
+ it "works in a plain method body" do
179
+ "def foo; bar; rescue; baz; end".
180
+ must_be_parsed_as s(:defn,
181
+ :foo,
182
+ s(:args),
183
+ s(:rescue,
184
+ s(:call, nil, :bar),
185
+ s(:resbody,
186
+ s(:array),
187
+ s(:call, nil, :baz))))
188
+ end
189
+
190
+ it "works in a method body inside begin..end" do
191
+ "def foo; bar; begin; baz; rescue; qux; end; quuz; end".
192
+ must_be_parsed_as s(:defn,
193
+ :foo,
194
+ s(:args),
195
+ s(:call, nil, :bar),
196
+ s(:rescue,
197
+ s(:call, nil, :baz),
198
+ s(:resbody, s(:array), s(:call, nil, :qux))),
199
+ s(:call, nil, :quuz))
200
+ end
201
+ end
202
+
203
+ describe "for the ensure statement" do
204
+ it "works with single statement main and ensure bodies" do
205
+ "begin; foo; ensure; bar; end".
206
+ must_be_parsed_as s(:ensure,
207
+ s(:call, nil, :foo),
208
+ s(:call, nil, :bar))
209
+ end
210
+
211
+ it "works with multi-statement main and ensure bodies" do
212
+ "begin; foo; bar; ensure; baz; qux; end".
213
+ must_be_parsed_as s(:ensure,
214
+ s(:block,
215
+ s(:call, nil, :foo),
216
+ s(:call, nil, :bar)),
217
+ s(:block,
218
+ s(:call, nil, :baz),
219
+ s(:call, nil, :qux)))
220
+ end
221
+
222
+ it "works together with rescue" do
223
+ "begin; foo; rescue; bar; ensure; baz; end".
224
+ must_be_parsed_as s(:ensure,
225
+ s(:rescue,
226
+ s(:call, nil, :foo),
227
+ s(:resbody,
228
+ s(:array),
229
+ s(:call, nil, :bar))),
230
+ s(:call, nil, :baz))
231
+ end
232
+
233
+ it "works with empty main and ensure bodies" do
234
+ "begin; ensure; end".
235
+ must_be_parsed_as s(:ensure, s(:nil))
236
+ end
237
+ end
238
+
239
+ describe "for lists of consecutive statments" do
240
+ it "removes extra blocks for grouped statements at the start of the list" do
241
+ "(foo; bar); baz".
242
+ must_be_parsed_as s(:block,
243
+ s(:call, nil, :foo),
244
+ s(:call, nil, :bar),
245
+ s(:call, nil, :baz))
246
+ end
247
+
248
+ it "keeps extra blocks for grouped statements at the end of the list" do
249
+ "foo; (bar; baz)".
250
+ must_be_parsed_as s(:block,
251
+ s(:call, nil, :foo),
252
+ s(:block,
253
+ s(:call, nil, :bar),
254
+ s(:call, nil, :baz)))
91
255
  end
92
256
  end
93
257
 
@@ -95,9 +259,17 @@ describe RipperRubyParser::Parser do
95
259
  it "works in the simple case" do
96
260
  "->(foo) { bar }".
97
261
  must_be_parsed_as s(:iter,
98
- s(:call, nil, :lambda, s(:arglist)),
99
- s(:lasgn, :foo),
100
- s(:call, nil, :bar, s(:arglist)))
262
+ s(:call, nil, :lambda),
263
+ s(:args, :foo),
264
+ s(:call, nil, :bar))
265
+ end
266
+
267
+ it "works when there are no arguments" do
268
+ "-> { bar }".
269
+ must_be_parsed_as s(:iter,
270
+ s(:call, nil, :lambda),
271
+ 0,
272
+ s(:call, nil, :bar))
101
273
  end
102
274
  end
103
275
  end