ripper_ruby_parser 0.0.1 → 0.0.2
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.
- 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
|