ripper_ruby_parser 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ripper_ruby_parser/commenting_sexp_builder.rb +48 -0
- data/lib/ripper_ruby_parser/parser.rb +4 -3
- data/lib/ripper_ruby_parser/sexp_handlers/arguments.rb +6 -2
- data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +1 -1
- data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +72 -19
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +68 -4
- data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +42 -14
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +41 -25
- data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +20 -0
- data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +17 -21
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +28 -4
- data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +39 -10
- data/lib/ripper_ruby_parser/sexp_processor.rb +109 -38
- data/lib/ripper_ruby_parser/version.rb +1 -1
- data/test/end_to_end/comments_test.rb +73 -0
- data/test/end_to_end/comparison_test.rb +60 -0
- data/test/end_to_end/line_numbering_test.rb +63 -0
- data/test/test_helper.rb +16 -4
- data/test/unit/commenting_sexp_builder_test.rb +75 -0
- data/test/unit/parser_test.rb +810 -15
- data/test/unit/sexp_processor_test.rb +23 -5
- metadata +19 -12
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
|
2
|
+
require 'ruby_parser'
|
3
|
+
|
4
|
+
describe "Using RipperRubyParser and RubyParser" do
|
5
|
+
def to_comments exp
|
6
|
+
inner = exp.map do |sub_exp|
|
7
|
+
if sub_exp.is_a? Sexp
|
8
|
+
to_comments sub_exp
|
9
|
+
else
|
10
|
+
sub_exp
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if exp.comments.nil?
|
15
|
+
s(*inner)
|
16
|
+
else
|
17
|
+
s(:comment, exp.comments, s(*inner))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
let :newparser do
|
22
|
+
RipperRubyParser::Parser.new
|
23
|
+
end
|
24
|
+
|
25
|
+
let :oldparser do
|
26
|
+
RubyParser.new
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "for a program with quite some comments" do
|
30
|
+
let :program do
|
31
|
+
<<-END
|
32
|
+
# Foo
|
33
|
+
class Foo
|
34
|
+
# The foo
|
35
|
+
# method
|
36
|
+
def foo
|
37
|
+
bar # bar
|
38
|
+
# internal comment
|
39
|
+
end
|
40
|
+
|
41
|
+
def bar
|
42
|
+
baz
|
43
|
+
end
|
44
|
+
end
|
45
|
+
# Quux
|
46
|
+
module Qux
|
47
|
+
class Quux
|
48
|
+
def bar
|
49
|
+
end
|
50
|
+
def baz
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
END
|
55
|
+
end
|
56
|
+
|
57
|
+
let :original do
|
58
|
+
oldparser.parse program
|
59
|
+
end
|
60
|
+
|
61
|
+
let :imitation do
|
62
|
+
newparser.parse program
|
63
|
+
end
|
64
|
+
|
65
|
+
it "gives the same result" do
|
66
|
+
imitation.must_equal original
|
67
|
+
end
|
68
|
+
|
69
|
+
it "gives the same result with comments" do
|
70
|
+
to_comments(imitation).must_equal to_comments(original)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -52,5 +52,65 @@ describe "Using RipperRubyParser and RubyParser" do
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
describe "for an example with yield from Reek" do
|
56
|
+
let :program do
|
57
|
+
'def fred() yield(3) if block_given?; end'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "gives the same result" do
|
61
|
+
original = oldparser.parse program
|
62
|
+
imitation = newparser.parse program
|
63
|
+
|
64
|
+
imitation.must_equal original
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "for an example with floats from Reek" do
|
69
|
+
let :program do
|
70
|
+
<<-END
|
71
|
+
def total_envy
|
72
|
+
fred = @item
|
73
|
+
total = 0
|
74
|
+
total += fred.price
|
75
|
+
total += fred.tax
|
76
|
+
total *= 1.15
|
77
|
+
end
|
78
|
+
END
|
79
|
+
end
|
80
|
+
|
81
|
+
it "gives the same result" do
|
82
|
+
original = oldparser.parse program
|
83
|
+
imitation = newparser.parse program
|
84
|
+
|
85
|
+
formatted(imitation).must_equal formatted(original)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "for a example with operators and explicit block parameter from Reek" do
|
90
|
+
let :program do
|
91
|
+
<<-END
|
92
|
+
def parse(arg, argv, &error)
|
93
|
+
if !(val = arg) and (argv.empty? or /\\A-/ =~ (val = argv[0]))
|
94
|
+
return nil, block, nil
|
95
|
+
end
|
96
|
+
opt = (val = parse_arg(val, &error))[1]
|
97
|
+
val = conv_arg(*val)
|
98
|
+
if opt and !arg
|
99
|
+
argv.shift
|
100
|
+
else
|
101
|
+
val[0] = nil
|
102
|
+
end
|
103
|
+
val
|
104
|
+
end
|
105
|
+
END
|
106
|
+
end
|
107
|
+
|
108
|
+
it "gives the same result" do
|
109
|
+
original = oldparser.parse program
|
110
|
+
imitation = newparser.parse program
|
111
|
+
|
112
|
+
formatted(imitation).must_equal formatted(original)
|
113
|
+
end
|
114
|
+
end
|
55
115
|
end
|
56
116
|
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
|
2
|
+
require 'ruby_parser'
|
3
|
+
|
4
|
+
describe "Using RipperRubyParser and RubyParser" do
|
5
|
+
def to_line_numbers exp
|
6
|
+
exp.map! do |sub_exp|
|
7
|
+
if sub_exp.is_a? Sexp
|
8
|
+
to_line_numbers sub_exp
|
9
|
+
else
|
10
|
+
sub_exp
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if exp.sexp_type == :scope
|
15
|
+
exp
|
16
|
+
else
|
17
|
+
s(:line_number, exp.line, exp)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
let :newparser do
|
22
|
+
RipperRubyParser::Parser.new
|
23
|
+
end
|
24
|
+
|
25
|
+
let :oldparser do
|
26
|
+
RubyParser.new
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "for a multi-line program" do
|
30
|
+
let :program do
|
31
|
+
<<-END
|
32
|
+
class Foo
|
33
|
+
def foo()
|
34
|
+
bar()
|
35
|
+
baz(qux)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module Bar
|
40
|
+
@@baz = {}
|
41
|
+
end
|
42
|
+
END
|
43
|
+
end
|
44
|
+
|
45
|
+
let :original do
|
46
|
+
oldparser.parse program
|
47
|
+
end
|
48
|
+
|
49
|
+
let :imitation do
|
50
|
+
newparser.parse program
|
51
|
+
end
|
52
|
+
|
53
|
+
it "gives the same result" do
|
54
|
+
imitation.must_equal original
|
55
|
+
end
|
56
|
+
|
57
|
+
it "gives the same result with line numbers" do
|
58
|
+
formatted(to_line_numbers(imitation)).
|
59
|
+
must_equal formatted(to_line_numbers(original))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
data/test/test_helper.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
if ENV["SIMPLECOV"]
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start
|
4
|
+
end
|
3
5
|
require 'minitest/spec'
|
4
6
|
require 'minitest/autorun'
|
5
7
|
|
@@ -7,6 +9,16 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
7
9
|
|
8
10
|
require 'ripper_ruby_parser'
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
class MiniTest::Unit::TestCase
|
13
|
+
def formatted exp
|
14
|
+
exp.to_s.gsub(/\), /, "),\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
def suppress_warnings
|
18
|
+
old_verbose = $VERBOSE
|
19
|
+
$VERBOSE = nil
|
20
|
+
result = yield
|
21
|
+
$VERBOSE = old_verbose
|
22
|
+
result
|
23
|
+
end
|
12
24
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe RipperRubyParser::CommentingSexpBuilder do
|
4
|
+
def parse_with_builder str
|
5
|
+
builder = RipperRubyParser::CommentingSexpBuilder.new str
|
6
|
+
builder.parse
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "handling comments" do
|
10
|
+
it "produces a comment node surrounding a commented def" do
|
11
|
+
result = parse_with_builder "# Foo\ndef foo; end"
|
12
|
+
result.must_equal [:program,
|
13
|
+
[[:comment,
|
14
|
+
"# Foo\n",
|
15
|
+
[:def,
|
16
|
+
[:@ident, "foo", [2, 4]],
|
17
|
+
[:params, nil, nil, nil, nil, nil],
|
18
|
+
[:bodystmt, [[:void_stmt]], nil, nil, nil]]]]]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "produces a blank comment node surrounding a def that has no comment" do
|
22
|
+
result = parse_with_builder "def foo; end"
|
23
|
+
result.must_equal [:program,
|
24
|
+
[[:comment,
|
25
|
+
"",
|
26
|
+
[:def,
|
27
|
+
[:@ident, "foo", [1, 4]],
|
28
|
+
[:params, nil, nil, nil, nil, nil],
|
29
|
+
[:bodystmt, [[:void_stmt]], nil, nil, nil]]]]]
|
30
|
+
end
|
31
|
+
|
32
|
+
it "produces a comment node surrounding a commented class" do
|
33
|
+
result = parse_with_builder "# Foo\nclass Foo; end"
|
34
|
+
result.must_equal [:program,
|
35
|
+
[[:comment,
|
36
|
+
"# Foo\n",
|
37
|
+
[:class,
|
38
|
+
[:const_ref, [:@const, "Foo", [2, 6]]],
|
39
|
+
nil,
|
40
|
+
[:bodystmt, [[:void_stmt]], nil, nil, nil]]]]]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "produce a blank comment node surrounding a class that has no comment" do
|
44
|
+
result = parse_with_builder "class Foo; end"
|
45
|
+
result.must_equal [:program,
|
46
|
+
[[:comment,
|
47
|
+
"",
|
48
|
+
[:class,
|
49
|
+
[:const_ref, [:@const, "Foo", [1, 6]]],
|
50
|
+
nil,
|
51
|
+
[:bodystmt, [[:void_stmt]], nil, nil, nil]]]]]
|
52
|
+
end
|
53
|
+
|
54
|
+
it "produces a comment node surrounding a commented module" do
|
55
|
+
result = parse_with_builder "# Foo\nmodule Foo; end"
|
56
|
+
result.must_equal [:program,
|
57
|
+
[[:comment,
|
58
|
+
"# Foo\n",
|
59
|
+
[:module,
|
60
|
+
[:const_ref, [:@const, "Foo", [2, 7]]],
|
61
|
+
[:bodystmt, [[:void_stmt]], nil, nil, nil]]]]]
|
62
|
+
end
|
63
|
+
|
64
|
+
it "produces a blank comment node surrounding a module that has no comment" do
|
65
|
+
result = parse_with_builder "module Foo; end"
|
66
|
+
result.must_equal [:program,
|
67
|
+
[[:comment,
|
68
|
+
"",
|
69
|
+
[:module,
|
70
|
+
[:const_ref, [:@const, "Foo", [1, 7]]],
|
71
|
+
[:bodystmt, [[:void_stmt]], nil, nil, nil]]]]]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
data/test/unit/parser_test.rb
CHANGED
@@ -19,6 +19,25 @@ describe RipperRubyParser::Parser do
|
|
19
19
|
sexp_p.verify
|
20
20
|
end
|
21
21
|
|
22
|
+
describe "for a class declaration" do
|
23
|
+
it "works with a namespaced class name" do
|
24
|
+
result = parser.parse "class Foo::Bar; end"
|
25
|
+
result.must_equal s(:class,
|
26
|
+
s(:colon2, s(:const, :Foo), :Bar),
|
27
|
+
nil,
|
28
|
+
s(:scope))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "for a module declaration" do
|
33
|
+
it "works with a namespaced module name" do
|
34
|
+
result = parser.parse "module Foo::Bar; end"
|
35
|
+
result.must_equal s(:module,
|
36
|
+
s(:colon2, s(:const, :Foo), :Bar),
|
37
|
+
s(:scope))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
22
41
|
describe "for if" do
|
23
42
|
it "works in the postfix case" do
|
24
43
|
result = parser.parse "foo if bar"
|
@@ -28,6 +47,14 @@ describe RipperRubyParser::Parser do
|
|
28
47
|
nil)
|
29
48
|
end
|
30
49
|
|
50
|
+
it "works in the block case" do
|
51
|
+
result = parser.parse "if foo; bar; end"
|
52
|
+
result.must_equal s(:if,
|
53
|
+
s(:call, nil, :foo, s(:arglist)),
|
54
|
+
s(:call, nil, :bar, s(:arglist)),
|
55
|
+
nil)
|
56
|
+
end
|
57
|
+
|
31
58
|
it "works with an else clause" do
|
32
59
|
result = parser.parse "if foo; bar; else; baz; end"
|
33
60
|
result.must_equal s(:if,
|
@@ -132,33 +159,219 @@ describe RipperRubyParser::Parser do
|
|
132
159
|
result.must_equal s(:return,
|
133
160
|
s(:call, nil, :foo, s(:arglist)))
|
134
161
|
end
|
162
|
+
|
163
|
+
it "works with a splat argument" do
|
164
|
+
result = parser.parse "return *foo"
|
165
|
+
result.must_equal s(:return,
|
166
|
+
s(:svalue,
|
167
|
+
s(:splat,
|
168
|
+
s(:call, nil, :foo, s(:arglist)))))
|
169
|
+
end
|
170
|
+
|
171
|
+
it "works with multiple arguments" do
|
172
|
+
result = parser.parse "return foo, bar"
|
173
|
+
result.must_equal s(:return,
|
174
|
+
s(:array,
|
175
|
+
s(:call, nil, :foo, s(:arglist)),
|
176
|
+
s(:call, nil, :bar, s(:arglist))))
|
177
|
+
end
|
178
|
+
|
179
|
+
it "works with a regular argument and a splat argument" do
|
180
|
+
result = parser.parse "return foo, *bar"
|
181
|
+
result.must_equal s(:return,
|
182
|
+
s(:array,
|
183
|
+
s(:call, nil, :foo, s(:arglist)),
|
184
|
+
s(:splat,
|
185
|
+
s(:call, nil, :bar, s(:arglist)))))
|
186
|
+
end
|
135
187
|
end
|
136
188
|
|
137
189
|
describe "for the until statement" do
|
138
|
-
it "works with do" do
|
190
|
+
it "works in the prefix block case with do" do
|
139
191
|
result = parser.parse "until foo do; bar; end"
|
140
192
|
result.must_equal s(:until,
|
141
193
|
s(:call, nil, :foo, s(:arglist)),
|
142
194
|
s(:call, nil, :bar, s(:arglist)), true)
|
143
195
|
end
|
144
196
|
|
145
|
-
it "works without do" do
|
197
|
+
it "works in the prefix block case without do" do
|
146
198
|
result = parser.parse "until foo; bar; end"
|
147
199
|
result.must_equal s(:until,
|
148
200
|
s(:call, nil, :foo, s(:arglist)),
|
149
201
|
s(:call, nil, :bar, s(:arglist)), true)
|
150
202
|
end
|
203
|
+
|
204
|
+
it "works in the single-line postfix case" do
|
205
|
+
result = parser.parse "foo until bar"
|
206
|
+
result.must_equal s(:until,
|
207
|
+
s(:call, nil, :bar, s(:arglist)),
|
208
|
+
s(:call, nil, :foo, s(:arglist)), true)
|
209
|
+
end
|
210
|
+
|
211
|
+
it "works in the block postfix case" do
|
212
|
+
result = parser.parse "begin; foo; end until bar"
|
213
|
+
result.must_equal s(:until,
|
214
|
+
s(:call, nil, :bar, s(:arglist)),
|
215
|
+
s(:call, nil, :foo, s(:arglist)), false)
|
216
|
+
end
|
151
217
|
end
|
152
218
|
|
153
|
-
describe "for
|
154
|
-
it "works
|
155
|
-
result = parser.parse "
|
156
|
-
result.must_equal s(:
|
219
|
+
describe "for the while statement" do
|
220
|
+
it "works with do" do
|
221
|
+
result = parser.parse "while foo do; bar; end"
|
222
|
+
result.must_equal s(:while,
|
223
|
+
s(:call, nil, :foo, s(:arglist)),
|
224
|
+
s(:call, nil, :bar, s(:arglist)), true)
|
157
225
|
end
|
158
226
|
|
159
|
-
it "works
|
160
|
-
result = parser.parse "
|
161
|
-
result.must_equal s(:
|
227
|
+
it "works without do" do
|
228
|
+
result = parser.parse "while foo; bar; end"
|
229
|
+
result.must_equal s(:while,
|
230
|
+
s(:call, nil, :foo, s(:arglist)),
|
231
|
+
s(:call, nil, :bar, s(:arglist)), true)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe "for the for statement" do
|
236
|
+
it "works with do" do
|
237
|
+
result = suppress_warnings {
|
238
|
+
parser.parse "for foo in bar do; baz; end" }
|
239
|
+
result.must_equal s(:for,
|
240
|
+
s(:call, nil, :bar, s(:arglist)),
|
241
|
+
s(:lasgn, :foo),
|
242
|
+
s(:call, nil, :baz, s(:arglist)))
|
243
|
+
end
|
244
|
+
|
245
|
+
it "works without do" do
|
246
|
+
result = suppress_warnings {
|
247
|
+
parser.parse "for foo in bar; baz; end" }
|
248
|
+
result.must_equal s(:for,
|
249
|
+
s(:call, nil, :bar, s(:arglist)),
|
250
|
+
s(:lasgn, :foo),
|
251
|
+
s(:call, nil, :baz, s(:arglist)))
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe "for a begin..end block" do
|
256
|
+
it "works with no statements" do
|
257
|
+
result = parser.parse "begin; end"
|
258
|
+
result.must_equal s(:nil)
|
259
|
+
end
|
260
|
+
|
261
|
+
it "works with one statement" do
|
262
|
+
result = parser.parse "begin; foo; end"
|
263
|
+
result.must_equal s(:call, nil, :foo, s(:arglist))
|
264
|
+
end
|
265
|
+
|
266
|
+
it "works with multiple statements" do
|
267
|
+
result = parser.parse "begin; foo; bar; end"
|
268
|
+
result.must_equal s(:block,
|
269
|
+
s(:call, nil, :foo, s(:arglist)),
|
270
|
+
s(:call, nil, :bar, s(:arglist)))
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
describe "for the rescue statement" do
|
275
|
+
it "works with single statement main and rescue bodies" do
|
276
|
+
result = parser.parse "begin; foo; rescue; bar; end"
|
277
|
+
result.must_equal s(:rescue,
|
278
|
+
s(:call, nil, :foo, s(:arglist)),
|
279
|
+
s(:resbody,
|
280
|
+
s(:array),
|
281
|
+
s(:call, nil, :bar, s(:arglist))))
|
282
|
+
end
|
283
|
+
|
284
|
+
it "works with multi-statement main and rescue bodies" do
|
285
|
+
result = parser.parse "begin; foo; bar; rescue; baz; qux; end"
|
286
|
+
result.must_equal s(:rescue,
|
287
|
+
s(:block,
|
288
|
+
s(:call, nil, :foo, s(:arglist)),
|
289
|
+
s(:call, nil, :bar, s(:arglist))),
|
290
|
+
s(:resbody,
|
291
|
+
s(:array),
|
292
|
+
s(:block,
|
293
|
+
s(:call, nil, :baz, s(:arglist)),
|
294
|
+
s(:call, nil, :qux, s(:arglist)))))
|
295
|
+
end
|
296
|
+
|
297
|
+
it "works with assignment to an error variable" do
|
298
|
+
result = suppress_warnings {
|
299
|
+
parser.parse "begin; foo; rescue => e; bar; end" }
|
300
|
+
result.must_equal s(:rescue,
|
301
|
+
s(:call, nil, :foo, s(:arglist)),
|
302
|
+
s(:resbody,
|
303
|
+
s(:array, s(:lasgn, :e, s(:gvar, :$!))),
|
304
|
+
s(:call, nil, :bar, s(:arglist))))
|
305
|
+
end
|
306
|
+
|
307
|
+
it "works with filtering of the exception type" do
|
308
|
+
result = parser.parse "begin; foo; rescue Bar; baz; end"
|
309
|
+
result.must_equal s(:rescue,
|
310
|
+
s(:call, nil, :foo, s(:arglist)),
|
311
|
+
s(:resbody,
|
312
|
+
s(:array, s(:const, :Bar)),
|
313
|
+
s(:call, nil, :baz, s(:arglist))))
|
314
|
+
end
|
315
|
+
|
316
|
+
it "works with filtering of the exception type and assignment to an error variable" do
|
317
|
+
result = suppress_warnings {
|
318
|
+
parser.parse "begin; foo; rescue Bar => e; baz; end" }
|
319
|
+
result.must_equal s(:rescue,
|
320
|
+
s(:call, nil, :foo, s(:arglist)),
|
321
|
+
s(:resbody,
|
322
|
+
s(:array,
|
323
|
+
s(:const, :Bar),
|
324
|
+
s(:lasgn, :e, s(:gvar, :$!))),
|
325
|
+
s(:call, nil, :baz, s(:arglist))))
|
326
|
+
end
|
327
|
+
|
328
|
+
it "works rescuing multiple exception types" do
|
329
|
+
result = parser.parse "begin; foo; rescue Bar, Baz; qux; end"
|
330
|
+
result.must_equal s(:rescue,
|
331
|
+
s(:call, nil, :foo, s(:arglist)),
|
332
|
+
s(:resbody,
|
333
|
+
s(:array, s(:const, :Bar), s(:const, :Baz)),
|
334
|
+
s(:call, nil, :qux, s(:arglist))))
|
335
|
+
end
|
336
|
+
|
337
|
+
it "works in the postfix case" do
|
338
|
+
result = parser.parse "foo rescue bar"
|
339
|
+
result.must_equal s(:rescue,
|
340
|
+
s(:call, nil, :foo, s(:arglist)),
|
341
|
+
s(:resbody,
|
342
|
+
s(:array),
|
343
|
+
s(:call, nil, :bar, s(:arglist))))
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
describe "for the ensure statement" do
|
348
|
+
it "works with single statement main and ensure bodies" do
|
349
|
+
result = parser.parse "begin; foo; ensure; bar; end"
|
350
|
+
result.must_equal s(:ensure,
|
351
|
+
s(:call, nil, :foo, s(:arglist)),
|
352
|
+
s(:call, nil, :bar, s(:arglist)))
|
353
|
+
end
|
354
|
+
|
355
|
+
it "works with multi-statement main and ensure bodies" do
|
356
|
+
result = parser.parse "begin; foo; bar; ensure; baz; qux; end"
|
357
|
+
result.must_equal s(:ensure,
|
358
|
+
s(:block,
|
359
|
+
s(:call, nil, :foo, s(:arglist)),
|
360
|
+
s(:call, nil, :bar, s(:arglist))),
|
361
|
+
s(:block,
|
362
|
+
s(:call, nil, :baz, s(:arglist)),
|
363
|
+
s(:call, nil, :qux, s(:arglist))))
|
364
|
+
end
|
365
|
+
|
366
|
+
it "works together with rescue" do
|
367
|
+
result = parser.parse "begin; foo; rescue; bar; ensure; baz; end"
|
368
|
+
result.must_equal s(:ensure,
|
369
|
+
s(:rescue,
|
370
|
+
s(:call, nil, :foo, s(:arglist)),
|
371
|
+
s(:resbody,
|
372
|
+
s(:array),
|
373
|
+
s(:call, nil, :bar, s(:arglist)))),
|
374
|
+
s(:call, nil, :baz, s(:arglist)))
|
162
375
|
end
|
163
376
|
end
|
164
377
|
|
@@ -181,6 +394,14 @@ describe RipperRubyParser::Parser do
|
|
181
394
|
s(:call, nil, :bar, s(:arglist)),
|
182
395
|
s(:splat, s(:call, nil, :baz, s(:arglist)))))
|
183
396
|
end
|
397
|
+
|
398
|
+
it "works for a simple case passing a block" do
|
399
|
+
result = parser.parse "foo &bar"
|
400
|
+
result.must_equal s(:call, nil, :foo,
|
401
|
+
s(:arglist,
|
402
|
+
s(:block_pass,
|
403
|
+
s(:call, nil, :bar, s(:arglist)))))
|
404
|
+
end
|
184
405
|
end
|
185
406
|
|
186
407
|
describe "for array literals" do
|
@@ -226,6 +447,13 @@ describe RipperRubyParser::Parser do
|
|
226
447
|
end
|
227
448
|
end
|
228
449
|
|
450
|
+
describe "for number literals" do
|
451
|
+
it "works for floats" do
|
452
|
+
result = parser.parse "3.14"
|
453
|
+
result.must_equal s(:lit, 3.14)
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
229
457
|
describe "for collection indexing" do
|
230
458
|
it "works in the simple case" do
|
231
459
|
result = parser.parse "foo[bar]"
|
@@ -273,6 +501,81 @@ describe RipperRubyParser::Parser do
|
|
273
501
|
s(:args, :bar),
|
274
502
|
s(:scope, s(:block, s(:nil))))
|
275
503
|
end
|
504
|
+
|
505
|
+
it "works with a simple splat" do
|
506
|
+
result = parser.parse "def foo *bar; end"
|
507
|
+
result.must_equal s(:defn,
|
508
|
+
:foo,
|
509
|
+
s(:args, :"*bar"),
|
510
|
+
s(:scope, s(:block, s(:nil))))
|
511
|
+
end
|
512
|
+
|
513
|
+
it "works with a regular argument plus splat" do
|
514
|
+
result = parser.parse "def foo bar, *baz; end"
|
515
|
+
result.must_equal s(:defn,
|
516
|
+
:foo,
|
517
|
+
s(:args, :bar, :"*baz"),
|
518
|
+
s(:scope, s(:block, s(:nil))))
|
519
|
+
end
|
520
|
+
|
521
|
+
it "works with a nameless splat" do
|
522
|
+
result = parser.parse "def foo *; end"
|
523
|
+
result.must_equal s(:defn,
|
524
|
+
:foo,
|
525
|
+
s(:args, :"*"),
|
526
|
+
s(:scope, s(:block, s(:nil))))
|
527
|
+
end
|
528
|
+
|
529
|
+
it "works for a simple case with explicit block parameter" do
|
530
|
+
result = parser.parse "def foo &bar; end"
|
531
|
+
result.must_equal s(:defn,
|
532
|
+
:foo,
|
533
|
+
s(:args, :"&bar"),
|
534
|
+
s(:scope, s(:block, s(:nil))))
|
535
|
+
end
|
536
|
+
|
537
|
+
it "works with a regular argument plus explicit block parameter" do
|
538
|
+
result = parser.parse "def foo bar, &baz; end"
|
539
|
+
result.must_equal s(:defn,
|
540
|
+
:foo,
|
541
|
+
s(:args, :bar, :"&baz"),
|
542
|
+
s(:scope, s(:block, s(:nil))))
|
543
|
+
end
|
544
|
+
|
545
|
+
it "works with a argument with default value plus explicit block parameter" do
|
546
|
+
result = parser.parse "def foo bar=1, &baz; end"
|
547
|
+
result.must_equal s(:defn,
|
548
|
+
:foo,
|
549
|
+
s(:args,
|
550
|
+
:bar, :"&baz",
|
551
|
+
s(:block,
|
552
|
+
s(:lasgn, :bar, s(:lit, 1)))),
|
553
|
+
s(:scope, s(:block, s(:nil))))
|
554
|
+
end
|
555
|
+
|
556
|
+
it "works with a splat plus explicit block parameter" do
|
557
|
+
result = parser.parse "def foo *bar, &baz; end"
|
558
|
+
result.must_equal s(:defn,
|
559
|
+
:foo,
|
560
|
+
s(:args, :"*bar", :"&baz"),
|
561
|
+
s(:scope, s(:block, s(:nil))))
|
562
|
+
end
|
563
|
+
|
564
|
+
it "works with an argument with default value plus splat" do
|
565
|
+
result = parser.parse "def foo bar=1, *baz; end"
|
566
|
+
result.must_equal s(:defn,
|
567
|
+
:foo,
|
568
|
+
s(:args, :bar, :"*baz",
|
569
|
+
s(:block,
|
570
|
+
s(:lasgn, :bar, s(:lit, 1)))),
|
571
|
+
s(:scope, s(:block, s(:nil))))
|
572
|
+
end
|
573
|
+
|
574
|
+
it "works when the method name is an operator" do
|
575
|
+
result = parser.parse "def +; end"
|
576
|
+
result.must_equal s(:defn, :+, s(:args),
|
577
|
+
s(:scope, s(:block, s(:nil))))
|
578
|
+
end
|
276
579
|
end
|
277
580
|
|
278
581
|
describe "for method calls" do
|
@@ -289,10 +592,20 @@ describe RipperRubyParser::Parser do
|
|
289
592
|
s(:arglist, s(:call, nil, :bar, s(:arglist))))
|
290
593
|
end
|
291
594
|
|
595
|
+
it "works with an empty parameter list and no brackets" do
|
596
|
+
result = parser.parse "foo"
|
597
|
+
result.must_equal s(:call, nil, :foo, s(:arglist))
|
598
|
+
end
|
599
|
+
|
292
600
|
it "works with brackets around an empty parameter list" do
|
293
601
|
result = parser.parse "foo()"
|
294
602
|
result.must_equal s(:call, nil, :foo, s(:arglist))
|
295
603
|
end
|
604
|
+
|
605
|
+
it "works for methods ending in a question mark" do
|
606
|
+
result = parser.parse "foo?"
|
607
|
+
result.must_equal s(:call, nil, :foo?, s(:arglist))
|
608
|
+
end
|
296
609
|
end
|
297
610
|
|
298
611
|
describe "with a reciever" do
|
@@ -351,6 +664,49 @@ describe RipperRubyParser::Parser do
|
|
351
664
|
end
|
352
665
|
end
|
353
666
|
|
667
|
+
describe "for yield" do
|
668
|
+
it "works with no arguments and no brackets" do
|
669
|
+
result = parser.parse "yield"
|
670
|
+
result.must_equal s(:yield)
|
671
|
+
end
|
672
|
+
|
673
|
+
it "works with brackets but no arguments" do
|
674
|
+
result = parser.parse "yield()"
|
675
|
+
result.must_equal s(:yield)
|
676
|
+
end
|
677
|
+
|
678
|
+
it "works with one argument and no brackets" do
|
679
|
+
result = parser.parse "yield foo"
|
680
|
+
result.must_equal s(:yield, s(:call, nil, :foo, s(:arglist)))
|
681
|
+
end
|
682
|
+
|
683
|
+
it "works with one argument and brackets" do
|
684
|
+
result = parser.parse "yield(foo)"
|
685
|
+
result.must_equal s(:yield, s(:call, nil, :foo, s(:arglist)))
|
686
|
+
end
|
687
|
+
|
688
|
+
it "works with multiple arguments and no brackets" do
|
689
|
+
result = parser.parse "yield foo, bar"
|
690
|
+
result.must_equal s(:yield,
|
691
|
+
s(:call, nil, :foo, s(:arglist)),
|
692
|
+
s(:call, nil, :bar, s(:arglist)))
|
693
|
+
end
|
694
|
+
|
695
|
+
it "works with multiple arguments and brackets" do
|
696
|
+
result = parser.parse "yield(foo, bar)"
|
697
|
+
result.must_equal s(:yield,
|
698
|
+
s(:call, nil, :foo, s(:arglist)),
|
699
|
+
s(:call, nil, :bar, s(:arglist)))
|
700
|
+
end
|
701
|
+
|
702
|
+
it "works with splat" do
|
703
|
+
result = parser.parse "yield foo, *bar"
|
704
|
+
result.must_equal s(:yield,
|
705
|
+
s(:call, nil, :foo, s(:arglist)),
|
706
|
+
s(:splat, s(:call, nil, :bar, s(:arglist))))
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
354
710
|
describe "for literals" do
|
355
711
|
it "works for symbols" do
|
356
712
|
result = parser.parse ":foo"
|
@@ -440,10 +796,17 @@ describe RipperRubyParser::Parser do
|
|
440
796
|
result.must_equal s(:lit, /\)\n\\/)
|
441
797
|
end
|
442
798
|
|
443
|
-
it "works for
|
799
|
+
it "works for simple dsyms" do
|
444
800
|
result = parser.parse ':"foo"'
|
445
801
|
result.must_equal s(:lit, :foo)
|
446
802
|
end
|
803
|
+
|
804
|
+
it "works for dsyms with interpolations" do
|
805
|
+
result = parser.parse ':"foo#{bar}"'
|
806
|
+
result.must_equal s(:dsym,
|
807
|
+
"foo",
|
808
|
+
s(:evstr, s(:call, nil, :bar, s(:arglist))))
|
809
|
+
end
|
447
810
|
end
|
448
811
|
|
449
812
|
describe "for the __FILE__ keyword" do
|
@@ -458,9 +821,26 @@ describe RipperRubyParser::Parser do
|
|
458
821
|
result = parser.parse "::Foo"
|
459
822
|
result.must_equal s(:colon3, :Foo)
|
460
823
|
end
|
824
|
+
|
825
|
+
it "works with a three-level constant lookup" do
|
826
|
+
result = parser.parse "Foo::Bar::Baz"
|
827
|
+
result.must_equal s(:colon2,
|
828
|
+
s(:colon2, s(:const, :Foo), :Bar),
|
829
|
+
:Baz)
|
830
|
+
end
|
461
831
|
end
|
462
832
|
|
463
833
|
describe "for variable references" do
|
834
|
+
it "works for self" do
|
835
|
+
result = parser.parse "self"
|
836
|
+
result.must_equal s(:self)
|
837
|
+
end
|
838
|
+
|
839
|
+
it "works for instance variables" do
|
840
|
+
result = parser.parse "@foo"
|
841
|
+
result.must_equal s(:ivar, :@foo)
|
842
|
+
end
|
843
|
+
|
464
844
|
it "works for global variables" do
|
465
845
|
result = parser.parse "$foo"
|
466
846
|
result.must_equal s(:gvar, :$foo)
|
@@ -470,6 +850,11 @@ describe RipperRubyParser::Parser do
|
|
470
850
|
result = parser.parse "$1"
|
471
851
|
result.must_equal s(:nth_ref, 1)
|
472
852
|
end
|
853
|
+
|
854
|
+
it "works for class variables" do
|
855
|
+
result = parser.parse "@@foo"
|
856
|
+
result.must_equal s(:cvar, :@@foo)
|
857
|
+
end
|
473
858
|
end
|
474
859
|
|
475
860
|
describe "for single assignment" do
|
@@ -496,11 +881,33 @@ describe RipperRubyParser::Parser do
|
|
496
881
|
s(:call, nil, :bar, s(:arglist)),
|
497
882
|
s(:call, nil, :baz, s(:arglist))))
|
498
883
|
end
|
884
|
+
|
885
|
+
it "works when assigning to an attribute" do
|
886
|
+
result = parser.parse "foo.bar = baz"
|
887
|
+
result.must_equal s(:attrasgn,
|
888
|
+
s(:call, nil, :foo, s(:arglist)),
|
889
|
+
:bar=,
|
890
|
+
s(:arglist, s(:call, nil, :baz, s(:arglist))))
|
891
|
+
end
|
892
|
+
|
893
|
+
it "works when assigning to a class variable" do
|
894
|
+
result = parser.parse "@@foo = bar"
|
895
|
+
result.must_equal s(:cvdecl,
|
896
|
+
:@@foo,
|
897
|
+
s(:call, nil, :bar, s(:arglist)))
|
898
|
+
end
|
899
|
+
|
900
|
+
it "works when assigning to a global variable" do
|
901
|
+
result = parser.parse "$foo = bar"
|
902
|
+
result.must_equal s(:gasgn,
|
903
|
+
:$foo,
|
904
|
+
s(:call, nil, :bar, s(:arglist)))
|
905
|
+
end
|
499
906
|
end
|
500
907
|
|
501
908
|
describe "for operator assignment" do
|
502
909
|
it "works with +=" do
|
503
|
-
result = parser.parse "foo += bar"
|
910
|
+
result = suppress_warnings { parser.parse "foo += bar" }
|
504
911
|
result.must_equal s(:lasgn,
|
505
912
|
:foo,
|
506
913
|
s(:call,
|
@@ -510,7 +917,7 @@ describe RipperRubyParser::Parser do
|
|
510
917
|
end
|
511
918
|
|
512
919
|
it "works with -=" do
|
513
|
-
result = parser.parse "foo -= bar"
|
920
|
+
result = suppress_warnings { parser.parse "foo -= bar" }
|
514
921
|
result.must_equal s(:lasgn,
|
515
922
|
:foo,
|
516
923
|
s(:call,
|
@@ -519,6 +926,14 @@ describe RipperRubyParser::Parser do
|
|
519
926
|
s(:arglist, s(:call, nil, :bar, s(:arglist)))))
|
520
927
|
end
|
521
928
|
|
929
|
+
it "works with ||=" do
|
930
|
+
result = suppress_warnings { parser.parse "foo ||= bar" }
|
931
|
+
result.must_equal s(:op_asgn_or,
|
932
|
+
s(:lvar, :foo),
|
933
|
+
s(:lasgn, :foo,
|
934
|
+
s(:call, nil, :bar, s(:arglist))))
|
935
|
+
end
|
936
|
+
|
522
937
|
it "works when assigning to an instance variable" do
|
523
938
|
result = parser.parse "@foo += bar"
|
524
939
|
result.must_equal s(:iasgn,
|
@@ -537,11 +952,38 @@ describe RipperRubyParser::Parser do
|
|
537
952
|
:+,
|
538
953
|
s(:call, nil, :baz, s(:arglist)))
|
539
954
|
end
|
955
|
+
|
956
|
+
it "works with ||= when assigning to a collection element" do
|
957
|
+
result = parser.parse "foo[bar] ||= baz"
|
958
|
+
result.must_equal s(:op_asgn1,
|
959
|
+
s(:call, nil, :foo, s(:arglist)),
|
960
|
+
s(:arglist, s(:call, nil, :bar, s(:arglist))),
|
961
|
+
:"||",
|
962
|
+
s(:call, nil, :baz, s(:arglist)))
|
963
|
+
end
|
964
|
+
|
965
|
+
it "works when assigning to an attribute" do
|
966
|
+
result = parser.parse "foo.bar += baz"
|
967
|
+
result.must_equal s(:op_asgn2,
|
968
|
+
s(:call, nil, :foo, s(:arglist)),
|
969
|
+
:bar=,
|
970
|
+
:+,
|
971
|
+
s(:call, nil, :baz, s(:arglist)))
|
972
|
+
end
|
973
|
+
|
974
|
+
it "works with ||= when assigning to an attribute" do
|
975
|
+
result = parser.parse "foo.bar ||= baz"
|
976
|
+
result.must_equal s(:op_asgn2,
|
977
|
+
s(:call, nil, :foo, s(:arglist)),
|
978
|
+
:bar=,
|
979
|
+
:"||",
|
980
|
+
s(:call, nil, :baz, s(:arglist)))
|
981
|
+
end
|
540
982
|
end
|
541
983
|
|
542
984
|
describe "for multiple assignment" do
|
543
985
|
it "works the same number of items on each side" do
|
544
|
-
result = parser.parse "foo, bar = baz, qux"
|
986
|
+
result = suppress_warnings { parser.parse "foo, bar = baz, qux" }
|
545
987
|
result.must_equal s(:masgn,
|
546
988
|
s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
|
547
989
|
s(:array,
|
@@ -550,7 +992,7 @@ describe RipperRubyParser::Parser do
|
|
550
992
|
end
|
551
993
|
|
552
994
|
it "works with a single item on the right-hand side" do
|
553
|
-
result = parser.parse "foo, bar = baz"
|
995
|
+
result = suppress_warnings { parser.parse "foo, bar = baz" }
|
554
996
|
result.must_equal s(:masgn,
|
555
997
|
s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
|
556
998
|
s(:to_ary,
|
@@ -558,16 +1000,117 @@ describe RipperRubyParser::Parser do
|
|
558
1000
|
end
|
559
1001
|
|
560
1002
|
it "works with left-hand splat" do
|
561
|
-
result = parser.parse "foo, *bar = baz, qux"
|
1003
|
+
result = suppress_warnings { parser.parse "foo, *bar = baz, qux" }
|
562
1004
|
result.must_equal s(:masgn,
|
563
1005
|
s(:array, s(:lasgn, :foo), s(:splat, s(:lasgn, :bar))),
|
564
1006
|
s(:array,
|
565
1007
|
s(:call, nil, :baz, s(:arglist)),
|
566
1008
|
s(:call, nil, :qux, s(:arglist))))
|
567
1009
|
end
|
1010
|
+
|
1011
|
+
it "works with brackets around the left-hand side" do
|
1012
|
+
result = suppress_warnings { parser.parse "(foo, bar) = baz" }
|
1013
|
+
result.must_equal s(:masgn,
|
1014
|
+
s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
|
1015
|
+
s(:to_ary,
|
1016
|
+
s(:call, nil, :baz, s(:arglist))))
|
1017
|
+
end
|
1018
|
+
|
1019
|
+
it "works with complex destructuring" do
|
1020
|
+
result = suppress_warnings { parser.parse "foo, (bar, baz) = qux" }
|
1021
|
+
result.must_equal s(:masgn,
|
1022
|
+
s(:array,
|
1023
|
+
s(:lasgn, :foo),
|
1024
|
+
s(:masgn,
|
1025
|
+
s(:array,
|
1026
|
+
s(:lasgn, :bar),
|
1027
|
+
s(:lasgn, :baz)))),
|
1028
|
+
s(:to_ary,
|
1029
|
+
s(:call, nil, :qux, s(:arglist))))
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
it "works with instance variables" do
|
1033
|
+
result = parser.parse "@foo, @bar = baz"
|
1034
|
+
result.must_equal s(:masgn,
|
1035
|
+
s(:array, s(:iasgn, :@foo), s(:iasgn, :@bar)),
|
1036
|
+
s(:to_ary,
|
1037
|
+
s(:call, nil, :baz, s(:arglist))))
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
it "works with class variables" do
|
1041
|
+
result = parser.parse "@@foo, @@bar = baz"
|
1042
|
+
result.must_equal s(:masgn,
|
1043
|
+
s(:array, s(:cvdecl, :@@foo), s(:cvdecl, :@@bar)),
|
1044
|
+
s(:to_ary,
|
1045
|
+
s(:call, nil, :baz, s(:arglist))))
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
it "works with attributes" do
|
1049
|
+
result = parser.parse "foo.bar, foo.baz = qux"
|
1050
|
+
result.must_equal s(:masgn,
|
1051
|
+
s(:array,
|
1052
|
+
s(:attrasgn,
|
1053
|
+
s(:call, nil, :foo, s(:arglist)),
|
1054
|
+
:bar=,
|
1055
|
+
s(:arglist)),
|
1056
|
+
s(:attrasgn,
|
1057
|
+
s(:call, nil, :foo, s(:arglist)),
|
1058
|
+
:baz=,
|
1059
|
+
s(:arglist))),
|
1060
|
+
s(:to_ary,
|
1061
|
+
s(:call, nil, :qux, s(:arglist))))
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
it "works with collection elements" do
|
1065
|
+
result = parser.parse "foo[1], bar[2] = baz"
|
1066
|
+
result.must_equal s(:masgn,
|
1067
|
+
s(:array,
|
1068
|
+
s(:attrasgn,
|
1069
|
+
s(:call, nil, :foo, s(:arglist)),
|
1070
|
+
:[]=,
|
1071
|
+
s(:arglist, s(:lit, 1))),
|
1072
|
+
s(:attrasgn,
|
1073
|
+
s(:call, nil, :bar, s(:arglist)),
|
1074
|
+
:[]=,
|
1075
|
+
s(:arglist, s(:lit, 2)))),
|
1076
|
+
s(:to_ary, s(:call, nil, :baz, s(:arglist))))
|
1077
|
+
end
|
1078
|
+
|
1079
|
+
it "works with constants" do
|
1080
|
+
result = parser.parse "Foo, Bar = baz"
|
1081
|
+
result.must_equal s(:masgn,
|
1082
|
+
s(:array, s(:cdecl, :Foo), s(:cdecl, :Bar)),
|
1083
|
+
s(:to_ary,
|
1084
|
+
s(:call, nil, :baz, s(:arglist))))
|
1085
|
+
end
|
1086
|
+
|
1087
|
+
it "works with instance variables and splat" do
|
1088
|
+
result = parser.parse "@foo, *@bar = baz"
|
1089
|
+
result.must_equal s(:masgn,
|
1090
|
+
s(:array,
|
1091
|
+
s(:iasgn, :@foo),
|
1092
|
+
s(:splat, s(:iasgn, :@bar))),
|
1093
|
+
s(:to_ary,
|
1094
|
+
s(:call, nil, :baz, s(:arglist))))
|
1095
|
+
end
|
1096
|
+
|
568
1097
|
end
|
569
1098
|
|
570
1099
|
describe "for operators" do
|
1100
|
+
it "handles :and" do
|
1101
|
+
result = parser.parse "foo and bar"
|
1102
|
+
result.must_equal s(:and,
|
1103
|
+
s(:call, nil, :foo, s(:arglist)),
|
1104
|
+
s(:call, nil, :bar, s(:arglist)))
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
it "handles :or" do
|
1108
|
+
result = parser.parse "foo or bar"
|
1109
|
+
result.must_equal s(:or,
|
1110
|
+
s(:call, nil, :foo, s(:arglist)),
|
1111
|
+
s(:call, nil, :bar, s(:arglist)))
|
1112
|
+
end
|
1113
|
+
|
571
1114
|
it "converts :&& to :and" do
|
572
1115
|
result = parser.parse "foo && bar"
|
573
1116
|
result.must_equal s(:and,
|
@@ -582,6 +1125,38 @@ describe RipperRubyParser::Parser do
|
|
582
1125
|
s(:call, nil, :bar, s(:arglist)))
|
583
1126
|
end
|
584
1127
|
|
1128
|
+
it "handles :!=" do
|
1129
|
+
result = parser.parse "foo != bar"
|
1130
|
+
result.must_equal s(:not,
|
1131
|
+
s(:call,
|
1132
|
+
s(:call, nil, :foo, s(:arglist)),
|
1133
|
+
:==,
|
1134
|
+
s(:arglist,
|
1135
|
+
s(:call, nil, :bar, s(:arglist)))))
|
1136
|
+
end
|
1137
|
+
|
1138
|
+
it "handles :=~ with two non-literals" do
|
1139
|
+
result = parser.parse "foo =~ bar"
|
1140
|
+
result.must_equal s(:call,
|
1141
|
+
s(:call, nil, :foo, s(:arglist)),
|
1142
|
+
:=~,
|
1143
|
+
s(:arglist, s(:call, nil, :bar, s(:arglist))))
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
it "handles :=~ with literal regexp on the left hand side" do
|
1147
|
+
result = parser.parse "/foo/ =~ bar"
|
1148
|
+
result.must_equal s(:match2,
|
1149
|
+
s(:lit, /foo/),
|
1150
|
+
s(:call, nil, :bar, s(:arglist)))
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
it "handles :=~ with literal regexp on the right hand side" do
|
1154
|
+
result = parser.parse "foo =~ /bar/"
|
1155
|
+
result.must_equal s(:match3,
|
1156
|
+
s(:lit, /bar/),
|
1157
|
+
s(:call, nil, :foo, s(:arglist)))
|
1158
|
+
end
|
1159
|
+
|
585
1160
|
it "handles unary minus with a number literal" do
|
586
1161
|
result = parser.parse "-1"
|
587
1162
|
result.must_equal s(:lit, -1)
|
@@ -595,6 +1170,29 @@ describe RipperRubyParser::Parser do
|
|
595
1170
|
s(:arglist))
|
596
1171
|
end
|
597
1172
|
|
1173
|
+
it "handles unary plus with a number literal" do
|
1174
|
+
result = parser.parse "+ 1"
|
1175
|
+
result.must_equal s(:lit, 1)
|
1176
|
+
end
|
1177
|
+
|
1178
|
+
it "handles unary plus with a non-literal" do
|
1179
|
+
result = parser.parse "+ foo"
|
1180
|
+
result.must_equal s(:call,
|
1181
|
+
s(:call, nil, :foo, s(:arglist)),
|
1182
|
+
:+@,
|
1183
|
+
s(:arglist))
|
1184
|
+
end
|
1185
|
+
|
1186
|
+
it "handles unary not" do
|
1187
|
+
result = parser.parse "not foo"
|
1188
|
+
result.must_equal s(:not, s(:call, nil, :foo, s(:arglist)))
|
1189
|
+
end
|
1190
|
+
|
1191
|
+
it "converts :! to :not" do
|
1192
|
+
result = parser.parse "!foo"
|
1193
|
+
result.must_equal s(:not, s(:call, nil, :foo, s(:arglist)))
|
1194
|
+
end
|
1195
|
+
|
598
1196
|
it "handles the range operator with positive number literals" do
|
599
1197
|
result = parser.parse "1..2"
|
600
1198
|
result.must_equal s(:lit, 1..2)
|
@@ -618,6 +1216,203 @@ describe RipperRubyParser::Parser do
|
|
618
1216
|
s(:call, nil, :foo, s(:arglist)),
|
619
1217
|
s(:call, nil, :bar, s(:arglist)))
|
620
1218
|
end
|
1219
|
+
|
1220
|
+
it "handles the ternary operator" do
|
1221
|
+
result = parser.parse "foo ? bar : baz"
|
1222
|
+
result.must_equal s(:if,
|
1223
|
+
s(:call, nil, :foo, s(:arglist)),
|
1224
|
+
s(:call, nil, :bar, s(:arglist)),
|
1225
|
+
s(:call, nil, :baz, s(:arglist)))
|
1226
|
+
end
|
1227
|
+
end
|
1228
|
+
|
1229
|
+
describe "for expressions" do
|
1230
|
+
it "handles assignment inside binary operator expressions" do
|
1231
|
+
result = suppress_warnings { parser.parse "foo + (bar = baz)" }
|
1232
|
+
result.must_equal s(:call,
|
1233
|
+
s(:call, nil, :foo, s(:arglist)),
|
1234
|
+
:+,
|
1235
|
+
s(:arglist,
|
1236
|
+
s(:lasgn,
|
1237
|
+
:bar,
|
1238
|
+
s(:call, nil, :baz, s(:arglist)))))
|
1239
|
+
end
|
1240
|
+
|
1241
|
+
it "handles assignment inside unary operator expressions" do
|
1242
|
+
result = suppress_warnings { parser.parse "+(foo = bar)" }
|
1243
|
+
result.must_equal s(:call,
|
1244
|
+
s(:lasgn, :foo, s(:call, nil, :bar, s(:arglist))),
|
1245
|
+
:+@,
|
1246
|
+
s(:arglist))
|
1247
|
+
end
|
1248
|
+
end
|
1249
|
+
|
1250
|
+
# Note: differences in the handling of comments are not caught by Sexp's
|
1251
|
+
# implementation of equality.
|
1252
|
+
describe "for comments" do
|
1253
|
+
it "handles method comments" do
|
1254
|
+
result = parser.parse "# Foo\ndef foo; end"
|
1255
|
+
result.must_equal s(:defn,
|
1256
|
+
:foo,
|
1257
|
+
s(:args), s(:scope, s(:block, s(:nil))))
|
1258
|
+
result.comments.must_equal "# Foo\n"
|
1259
|
+
end
|
1260
|
+
|
1261
|
+
it "matches comments to the correct entity" do
|
1262
|
+
result = parser.parse "# Foo\nclass Foo\n# Bar\ndef bar\nend\nend"
|
1263
|
+
result.must_equal s(:class, :Foo, nil,
|
1264
|
+
s(:scope,
|
1265
|
+
s(:defn, :bar,
|
1266
|
+
s(:args), s(:scope, s(:block, s(:nil))))))
|
1267
|
+
result.comments.must_equal "# Foo\n"
|
1268
|
+
defn = result[3][1]
|
1269
|
+
defn.sexp_type.must_equal :defn
|
1270
|
+
defn.comments.must_equal "# Bar\n"
|
1271
|
+
end
|
1272
|
+
|
1273
|
+
it "combines multi-line comments" do
|
1274
|
+
result = parser.parse "# Foo\n# Bar\ndef foo; end"
|
1275
|
+
result.must_equal s(:defn,
|
1276
|
+
:foo,
|
1277
|
+
s(:args), s(:scope, s(:block, s(:nil))))
|
1278
|
+
result.comments.must_equal "# Foo\n# Bar\n"
|
1279
|
+
end
|
1280
|
+
end
|
1281
|
+
|
1282
|
+
# Note: differences in the handling of line numbers are not caught by
|
1283
|
+
# Sexp's implementation of equality.
|
1284
|
+
describe "assigning line numbers" do
|
1285
|
+
it "works for a plain method call" do
|
1286
|
+
result = parser.parse "foo"
|
1287
|
+
result.line.must_equal 1
|
1288
|
+
end
|
1289
|
+
|
1290
|
+
it "works for a method call with brackets" do
|
1291
|
+
result = parser.parse "foo()"
|
1292
|
+
result.line.must_equal 1
|
1293
|
+
end
|
1294
|
+
|
1295
|
+
it "works for a method call with reciever" do
|
1296
|
+
result = parser.parse "foo.bar"
|
1297
|
+
result.line.must_equal 1
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
it "works for a method call with reciever and arguments" do
|
1301
|
+
result = parser.parse "foo.bar baz"
|
1302
|
+
result.line.must_equal 1
|
1303
|
+
end
|
1304
|
+
|
1305
|
+
it "works for a method call with arguments" do
|
1306
|
+
result = parser.parse "foo bar"
|
1307
|
+
result.line.must_equal 1
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
it "works for a block with two lines" do
|
1311
|
+
result = parser.parse "foo\nbar\n"
|
1312
|
+
result.sexp_type.must_equal :block
|
1313
|
+
result[1].line.must_equal 1
|
1314
|
+
result[2].line.must_equal 2
|
1315
|
+
result.line.must_equal 1
|
1316
|
+
end
|
1317
|
+
|
1318
|
+
it "works for a constant reference" do
|
1319
|
+
result = parser.parse "Foo"
|
1320
|
+
result.line.must_equal 1
|
1321
|
+
end
|
1322
|
+
|
1323
|
+
it "works for an instance variable" do
|
1324
|
+
result = parser.parse "@foo"
|
1325
|
+
result.line.must_equal 1
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
it "works for a global variable" do
|
1329
|
+
result = parser.parse "$foo"
|
1330
|
+
result.line.must_equal 1
|
1331
|
+
end
|
1332
|
+
|
1333
|
+
it "works for a class variable" do
|
1334
|
+
result = parser.parse "@@foo"
|
1335
|
+
result.line.must_equal 1
|
1336
|
+
end
|
1337
|
+
|
1338
|
+
it "works for a local variable" do
|
1339
|
+
result = parser.parse "foo = bar\nfoo\n"
|
1340
|
+
result.sexp_type.must_equal :block
|
1341
|
+
result[1].line.must_equal 1
|
1342
|
+
result[2].line.must_equal 2
|
1343
|
+
result.line.must_equal 1
|
1344
|
+
end
|
1345
|
+
|
1346
|
+
it "works for an integer literal" do
|
1347
|
+
result = parser.parse "42"
|
1348
|
+
result.line.must_equal 1
|
1349
|
+
end
|
1350
|
+
|
1351
|
+
it "works for a float literal" do
|
1352
|
+
result = parser.parse "3.14"
|
1353
|
+
result.line.must_equal 1
|
1354
|
+
end
|
1355
|
+
|
1356
|
+
it "works for a regular expression back reference" do
|
1357
|
+
result = parser.parse "$1"
|
1358
|
+
result.line.must_equal 1
|
1359
|
+
end
|
1360
|
+
|
1361
|
+
it "works for self" do
|
1362
|
+
result = parser.parse "self"
|
1363
|
+
result.line.must_equal 1
|
1364
|
+
end
|
1365
|
+
|
1366
|
+
it "works for __FILE__" do
|
1367
|
+
result = parser.parse "__FILE__"
|
1368
|
+
result.line.must_equal 1
|
1369
|
+
end
|
1370
|
+
|
1371
|
+
it "works for nil" do
|
1372
|
+
result = parser.parse "nil"
|
1373
|
+
result.line.must_equal 1
|
1374
|
+
end
|
1375
|
+
|
1376
|
+
it "works for a symbol literal" do
|
1377
|
+
result = parser.parse ":foo"
|
1378
|
+
result.line.must_equal 1
|
1379
|
+
end
|
1380
|
+
|
1381
|
+
it "works for a class definition" do
|
1382
|
+
result = parser.parse "class Foo; end"
|
1383
|
+
result.line.must_equal 1
|
1384
|
+
end
|
1385
|
+
|
1386
|
+
it "works for a module definition" do
|
1387
|
+
result = parser.parse "module Foo; end"
|
1388
|
+
result.line.must_equal 1
|
1389
|
+
end
|
1390
|
+
|
1391
|
+
it "works for a method definition" do
|
1392
|
+
result = parser.parse "def foo; end"
|
1393
|
+
result.line.must_equal 1
|
1394
|
+
end
|
1395
|
+
|
1396
|
+
it "works for assignment of the empty hash" do
|
1397
|
+
result = suppress_warnings { parser.parse "foo = {}" }
|
1398
|
+
result.line.must_equal 1
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
it "works for multiple assignment of empty hashes" do
|
1402
|
+
result = suppress_warnings { parser.parse "foo, bar = {}, {}" }
|
1403
|
+
result.line.must_equal 1
|
1404
|
+
end
|
1405
|
+
|
1406
|
+
it "assigns line numbers to all nested sexps" do
|
1407
|
+
result = parser.parse "foo() do\nend\n"
|
1408
|
+
result.must_equal s(:iter,
|
1409
|
+
s(:call,
|
1410
|
+
nil, :foo, s(:arglist)), nil, s(:block))
|
1411
|
+
arglist = result[1][3]
|
1412
|
+
block = result[3]
|
1413
|
+
nums = [ arglist.line, block.line ]
|
1414
|
+
nums.must_equal [1, 1]
|
1415
|
+
end
|
621
1416
|
end
|
622
1417
|
end
|
623
1418
|
end
|