ripper_ruby_parser 0.0.8 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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