ripper_ruby_parser 1.7.1 → 1.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/lib/ripper_ruby_parser/sexp_handlers.rb +2 -0
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +7 -2
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +15 -242
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +15 -13
- data/lib/ripper_ruby_parser/sexp_handlers/string_literals.rb +260 -0
- data/lib/ripper_ruby_parser/sexp_processor.rb +5 -38
- data/lib/ripper_ruby_parser/unescape.rb +23 -18
- data/lib/ripper_ruby_parser/version.rb +1 -1
- data/test/end_to_end/lib_comparison_test.rb +1 -12
- data/test/end_to_end/test_comparison_test.rb +1 -15
- data/test/ripper_ruby_parser/parser_test.rb +31 -8
- data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +4 -17
- data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +22 -0
- data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +5 -954
- data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +0 -30
- data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +12 -4
- data/test/ripper_ruby_parser/sexp_handlers/string_literals_test.rb +973 -0
- data/test/ripper_ruby_parser/sexp_processor_test.rb +24 -0
- data/test/samples/misc.rb +4 -0
- data/test/samples/number.rb +2 -0
- data/test/samples/strings.rb +0 -1
- data/test/test_helper.rb +9 -5
- metadata +6 -3
@@ -17,25 +17,11 @@ module RipperRubyParser
|
|
17
17
|
def initialize(filename: nil, extra_compatible: nil)
|
18
18
|
super()
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
@processors[:@const] = :process_at_const
|
27
|
-
@processors[:@ident] = :process_at_ident
|
28
|
-
@processors[:@cvar] = :process_at_cvar
|
29
|
-
@processors[:@gvar] = :process_at_gvar
|
30
|
-
@processors[:@ivar] = :process_at_ivar
|
31
|
-
@processors[:@kw] = :process_at_kw
|
32
|
-
@processors[:@op] = :process_at_op
|
33
|
-
@processors[:@backref] = :process_at_backref
|
34
|
-
|
35
|
-
@processors[:@backtick] = :process_at_backtick
|
36
|
-
@processors[:@period] = :process_at_period
|
37
|
-
|
38
|
-
@processors[:@tstring_content] = :process_at_tstring_content
|
20
|
+
public_methods.each do |name|
|
21
|
+
if name =~ /^process_at_(.*)/
|
22
|
+
@processors["@#{Regexp.last_match(1)}".to_sym] = name.to_sym
|
23
|
+
end
|
24
|
+
end
|
39
25
|
|
40
26
|
@filename = filename
|
41
27
|
@extra_compatible = extra_compatible
|
@@ -172,25 +158,6 @@ module RipperRubyParser
|
|
172
158
|
with_position pos, s(:iter, s(:postexe), 0, *body)
|
173
159
|
end
|
174
160
|
|
175
|
-
# number literals
|
176
|
-
def process_at_int(exp)
|
177
|
-
make_literal(exp) { |val| Integer(val) }
|
178
|
-
end
|
179
|
-
|
180
|
-
def process_at_float(exp)
|
181
|
-
make_literal(exp, &:to_f)
|
182
|
-
end
|
183
|
-
|
184
|
-
def process_at_rational(exp)
|
185
|
-
make_literal(exp, &:to_r)
|
186
|
-
end
|
187
|
-
|
188
|
-
# character literals
|
189
|
-
def process_at_CHAR(exp)
|
190
|
-
_, val, pos = exp.shift 3
|
191
|
-
with_position(pos, s(:str, unescape(val[1..-1])))
|
192
|
-
end
|
193
|
-
|
194
161
|
def process_at_label(exp)
|
195
162
|
make_literal(exp) { |val| val.chop.to_sym }
|
196
163
|
end
|
@@ -9,7 +9,7 @@ module RipperRubyParser
|
|
9
9
|
/\\(
|
10
10
|
[0-7]{1,3} | # octal character
|
11
11
|
x[0-9a-fA-F]{1,2} | # hex byte
|
12
|
-
u[0-9a-fA-F]
|
12
|
+
u[0-9a-fA-F]{4} | # unicode character
|
13
13
|
u{[0-9a-fA-F]{4,6}} | # unicode character
|
14
14
|
M-\\C-. | # meta-ctrl
|
15
15
|
C-\\M-. | # ctrl-meta
|
@@ -18,8 +18,8 @@ module RipperRubyParser
|
|
18
18
|
C-. | # control (regular)
|
19
19
|
c. | # control (shorthand)
|
20
20
|
M-. | # meta
|
21
|
-
\n | # line
|
22
|
-
. # single
|
21
|
+
\n | # line break
|
22
|
+
. # other single character
|
23
23
|
)/x.freeze
|
24
24
|
|
25
25
|
SINGLE_LETTER_ESCAPES = {
|
@@ -38,23 +38,28 @@ module RipperRubyParser
|
|
38
38
|
Regexp.new("^[#{SINGLE_LETTER_ESCAPES.keys.join}]$")
|
39
39
|
|
40
40
|
def simple_unescape(string)
|
41
|
-
string.gsub(
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
string.gsub(/
|
42
|
+
\\ # a backslash
|
43
|
+
( # followed by a
|
44
|
+
' | # single quote or
|
45
|
+
\\ # backslash
|
46
|
+
)/x) do
|
47
|
+
Regexp.last_match[1]
|
48
|
+
end
|
47
49
|
end
|
48
50
|
|
49
51
|
def simple_unescape_wordlist_word(string)
|
50
|
-
string.gsub(
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
string.gsub(/
|
53
|
+
\\ # a backslash
|
54
|
+
( # followed by a
|
55
|
+
' | # single quote or
|
56
|
+
\\ | # backslash or
|
57
|
+
[ ] | # space or
|
58
|
+
\n # newline
|
59
|
+
)
|
60
|
+
/x) do
|
61
|
+
Regexp.last_match[1]
|
62
|
+
end
|
58
63
|
end
|
59
64
|
|
60
65
|
def unescape(string)
|
@@ -106,7 +111,7 @@ module RipperRubyParser
|
|
106
111
|
when /^u\{/
|
107
112
|
hex_to_unicode_char(bare[2..-2])
|
108
113
|
when /^u/
|
109
|
-
hex_to_unicode_char(bare[1..4])
|
114
|
+
hex_to_unicode_char(bare[1..4])
|
110
115
|
when /^(c|C-).$/
|
111
116
|
control(bare[-1].ord).chr
|
112
117
|
when /^M-.$/
|
@@ -4,14 +4,6 @@ require File.expand_path("../test_helper.rb", File.dirname(__FILE__))
|
|
4
4
|
require "ruby_parser"
|
5
5
|
|
6
6
|
describe "Using RipperRubyParser and RubyParser" do
|
7
|
-
let :newparser do
|
8
|
-
RipperRubyParser::Parser.new
|
9
|
-
end
|
10
|
-
|
11
|
-
let :oldparser do
|
12
|
-
RubyParser.for_current_ruby
|
13
|
-
end
|
14
|
-
|
15
7
|
Dir.glob("lib/**/*.rb").each do |file|
|
16
8
|
describe "for #{file}" do
|
17
9
|
let :program do
|
@@ -19,10 +11,7 @@ describe "Using RipperRubyParser and RubyParser" do
|
|
19
11
|
end
|
20
12
|
|
21
13
|
it "gives the same result" do
|
22
|
-
|
23
|
-
imitation = newparser.parse program
|
24
|
-
|
25
|
-
_(formatted(imitation)).must_equal formatted(original)
|
14
|
+
_(program).must_be_parsed_as_before
|
26
15
|
end
|
27
16
|
end
|
28
17
|
end
|
@@ -4,14 +4,6 @@ require File.expand_path("../test_helper.rb", File.dirname(__FILE__))
|
|
4
4
|
require "ruby_parser"
|
5
5
|
|
6
6
|
describe "Using RipperRubyParser and RubyParser" do
|
7
|
-
let :newparser do
|
8
|
-
RipperRubyParser::Parser.new
|
9
|
-
end
|
10
|
-
|
11
|
-
let :oldparser do
|
12
|
-
RubyParser.for_current_ruby
|
13
|
-
end
|
14
|
-
|
15
7
|
Dir.glob("test/ripper_ruby_parser/**/*.rb").each do |file|
|
16
8
|
describe "for #{file}" do
|
17
9
|
let :program do
|
@@ -19,13 +11,7 @@ describe "Using RipperRubyParser and RubyParser" do
|
|
19
11
|
end
|
20
12
|
|
21
13
|
it "gives the same result" do
|
22
|
-
|
23
|
-
# inside.
|
24
|
-
copy = program.clone
|
25
|
-
original = oldparser.parse program
|
26
|
-
imitation = newparser.parse copy
|
27
|
-
|
28
|
-
_(formatted(imitation)).must_equal formatted(original)
|
14
|
+
_(program).must_be_parsed_as_before
|
29
15
|
end
|
30
16
|
end
|
31
17
|
end
|
@@ -324,6 +324,15 @@ describe RipperRubyParser::Parser do
|
|
324
324
|
_(result[4].comments).must_equal "# bar\n"
|
325
325
|
end
|
326
326
|
|
327
|
+
it "handles the use of symbols that are keywords" do
|
328
|
+
result = parser.parse "# Foo\ndef bar\n:class\nend"
|
329
|
+
_(result).must_equal s(:defn,
|
330
|
+
:bar,
|
331
|
+
s(:args),
|
332
|
+
s(:lit, :class))
|
333
|
+
_(result.comments).must_equal "# Foo\n"
|
334
|
+
end
|
335
|
+
|
327
336
|
it "handles use of singleton class inside methods" do
|
328
337
|
result = parser.parse "# Foo\ndef bar\nclass << self\nbaz\nend\nend"
|
329
338
|
_(result).must_equal s(:defn,
|
@@ -336,13 +345,11 @@ describe RipperRubyParser::Parser do
|
|
336
345
|
|
337
346
|
# TODO: Prefer assigning comment to the BEGIN instead
|
338
347
|
it "assigns comments on BEGIN blocks to the following item" do
|
339
|
-
result = parser.parse "# Bar\nBEGIN { }\n# Foo\
|
348
|
+
result = parser.parse "# Bar\nBEGIN { }\n# Foo\ndef foo; end"
|
340
349
|
_(result).must_equal s(:block,
|
341
350
|
s(:iter, s(:preexe), 0),
|
342
|
-
s(:
|
343
|
-
s(:defn, :foo, s(:args), s(:nil))))
|
351
|
+
s(:defn, :foo, s(:args), s(:nil)))
|
344
352
|
_(result[2].comments).must_equal "# Bar\n# Foo\n"
|
345
|
-
_(result[2][3].comments).must_equal "# foo\n"
|
346
353
|
end
|
347
354
|
|
348
355
|
it "assigns comments on multiple BEGIN blocks to the following item" do
|
@@ -355,12 +362,13 @@ describe RipperRubyParser::Parser do
|
|
355
362
|
end
|
356
363
|
|
357
364
|
it "assigns comments on BEGIN blocks to the first following item" do
|
358
|
-
result = parser.parse "# Bar\nBEGIN { }\n#
|
365
|
+
result = parser.parse "# Bar\nBEGIN { }\n# Foo\nclass Bar\n# foo\ndef foo; end\nend"
|
359
366
|
_(result).must_equal s(:block,
|
360
367
|
s(:iter, s(:preexe), 0),
|
361
|
-
s(:
|
362
|
-
|
363
|
-
_(result[
|
368
|
+
s(:class, :Bar, nil,
|
369
|
+
s(:defn, :foo, s(:args), s(:nil))))
|
370
|
+
_(result[2].comments).must_equal "# Bar\n# Foo\n"
|
371
|
+
_(result[2][3].comments).must_equal "# foo\n"
|
364
372
|
end
|
365
373
|
end
|
366
374
|
|
@@ -493,6 +501,11 @@ describe RipperRubyParser::Parser do
|
|
493
501
|
_(result.line).must_equal 1
|
494
502
|
end
|
495
503
|
|
504
|
+
it "works for a symbol literal" do
|
505
|
+
result = parser.parse ":foo"
|
506
|
+
_(result.line).must_equal 1
|
507
|
+
end
|
508
|
+
|
496
509
|
it "works for a class definition" do
|
497
510
|
result = parser.parse "class Foo; end"
|
498
511
|
_(result.line).must_equal 1
|
@@ -508,6 +521,16 @@ describe RipperRubyParser::Parser do
|
|
508
521
|
_(result.line).must_equal 1
|
509
522
|
end
|
510
523
|
|
524
|
+
it "works for assignment of the empty hash" do
|
525
|
+
result = parser.parse "foo = {}"
|
526
|
+
_(result.line).must_equal 1
|
527
|
+
end
|
528
|
+
|
529
|
+
it "works for multiple assignment of empty hashes" do
|
530
|
+
result = parser.parse "foo, bar = {}, {}"
|
531
|
+
_(result.line).must_equal 1
|
532
|
+
end
|
533
|
+
|
511
534
|
it "assigns line numbers to nested sexps without their own line numbers" do
|
512
535
|
_("foo(bar) do\nnext baz\nend\n")
|
513
536
|
.must_be_parsed_as s(:iter,
|
@@ -205,22 +205,6 @@ describe RipperRubyParser::Parser do
|
|
205
205
|
s(:call, s(:const, :Bar), :baz, s(:call, nil, :qux)),
|
206
206
|
s(:resbody, s(:array), s(:call, nil, :quuz))))
|
207
207
|
end
|
208
|
-
|
209
|
-
it "works with a method call with argument without brackets" do
|
210
|
-
_("foo = bar baz rescue qux")
|
211
|
-
.must_be_parsed_as s(:lasgn, :foo,
|
212
|
-
s(:rescue,
|
213
|
-
s(:call, nil, :bar, s(:call, nil, :baz)),
|
214
|
-
s(:resbody, s(:array), s(:call, nil, :qux))))
|
215
|
-
end
|
216
|
-
|
217
|
-
it "works with a class method call with argument without brackets" do
|
218
|
-
_("foo = Bar.baz qux rescue quuz")
|
219
|
-
.must_be_parsed_as s(:lasgn, :foo,
|
220
|
-
s(:rescue,
|
221
|
-
s(:call, s(:const, :Bar), :baz, s(:call, nil, :qux)),
|
222
|
-
s(:resbody, s(:array), s(:call, nil, :quuz))))
|
223
|
-
end
|
224
208
|
end
|
225
209
|
|
226
210
|
it "sets the correct line numbers" do
|
@@ -448,7 +432,10 @@ describe RipperRubyParser::Parser do
|
|
448
432
|
it "handles safe-assigning to an attribute of the collection element" do
|
449
433
|
_("foo[bar]&.baz = qux")
|
450
434
|
.must_be_parsed_as s(:safe_attrasgn,
|
451
|
-
s(:call,
|
435
|
+
s(:call,
|
436
|
+
s(:call, nil, :foo),
|
437
|
+
:[],
|
438
|
+
s(:call, nil, :bar)),
|
452
439
|
:baz=,
|
453
440
|
s(:call, nil, :qux))
|
454
441
|
end
|
@@ -170,6 +170,14 @@ describe RipperRubyParser::Parser do
|
|
170
170
|
s(:lvar, :bar)))
|
171
171
|
end
|
172
172
|
|
173
|
+
it "works with a nameless kwrest argument" do
|
174
|
+
_("foo do |**|; bar; end")
|
175
|
+
.must_be_parsed_as s(:iter,
|
176
|
+
s(:call, nil, :foo),
|
177
|
+
s(:args, :**),
|
178
|
+
s(:call, nil, :bar))
|
179
|
+
end
|
180
|
+
|
173
181
|
it "works with a regular argument after a splat argument" do
|
174
182
|
_("foo do |*bar, baz|; end")
|
175
183
|
.must_be_parsed_as s(:iter,
|
@@ -186,6 +194,15 @@ describe RipperRubyParser::Parser do
|
|
186
194
|
s(:lvar, :bar),
|
187
195
|
s(:lvar, :baz)))
|
188
196
|
end
|
197
|
+
|
198
|
+
it "works with a combination of regular arguments and an anonymous kwrest argument" do
|
199
|
+
_("foo do |bar, **|; qux bar; end")
|
200
|
+
.must_be_parsed_as s(:iter,
|
201
|
+
s(:call, nil, :foo),
|
202
|
+
s(:args, :bar, :"**"),
|
203
|
+
s(:call, nil, :qux,
|
204
|
+
s(:lvar, :bar)))
|
205
|
+
end
|
189
206
|
end
|
190
207
|
|
191
208
|
describe "for begin" do
|
@@ -219,6 +236,11 @@ describe RipperRubyParser::Parser do
|
|
219
236
|
nil,
|
220
237
|
s(:begin, s(:call, nil, :foo)))
|
221
238
|
end
|
239
|
+
|
240
|
+
it "removes :begin for a method receiver" do
|
241
|
+
_("begin; foo; end.bar")
|
242
|
+
.must_be_parsed_as s(:call, s(:call, nil, :foo), :bar)
|
243
|
+
end
|
222
244
|
end
|
223
245
|
|
224
246
|
describe "for rescue/else" do
|
@@ -6,820 +6,6 @@ describe RipperRubyParser::Parser do
|
|
6
6
|
let(:parser) { RipperRubyParser::Parser.new }
|
7
7
|
|
8
8
|
describe "#parse" do
|
9
|
-
describe "for regexp literals" do
|
10
|
-
it "works for a simple regex literal" do
|
11
|
-
_("/foo/")
|
12
|
-
.must_be_parsed_as s(:lit, /foo/)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "works for regex literals with escaped right parenthesis" do
|
16
|
-
_('/\\)/')
|
17
|
-
.must_be_parsed_as s(:lit, /\)/)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "works for regex literals with escape sequences" do
|
21
|
-
_('/\\)\\n\\\\/')
|
22
|
-
.must_be_parsed_as s(:lit, /\)\n\\/)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "does not fix encoding" do
|
26
|
-
_('/2\302\275/')
|
27
|
-
.must_be_parsed_as s(:lit, /2\302\275/)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "works for a regex literal with the multiline flag" do
|
31
|
-
_("/foo/m")
|
32
|
-
.must_be_parsed_as s(:lit, /foo/m)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "works for a regex literal with the extended flag" do
|
36
|
-
_("/foo/x")
|
37
|
-
.must_be_parsed_as s(:lit, /foo/x)
|
38
|
-
end
|
39
|
-
|
40
|
-
it "works for a regex literal with the ignorecase flag" do
|
41
|
-
_("/foo/i")
|
42
|
-
.must_be_parsed_as s(:lit, /foo/i)
|
43
|
-
end
|
44
|
-
|
45
|
-
it "works for a regex literal with a combination of flags" do
|
46
|
-
_("/foo/ixmn")
|
47
|
-
.must_be_parsed_as s(:lit, /foo/mixn)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "works with the no-encoding flag" do
|
51
|
-
_("/foo/n")
|
52
|
-
.must_be_parsed_as s(:lit, /foo/n)
|
53
|
-
end
|
54
|
-
|
55
|
-
it "works with line continuation" do
|
56
|
-
_("/foo\\\nbar/")
|
57
|
-
.must_be_parsed_as s(:lit, /foobar/)
|
58
|
-
end
|
59
|
-
|
60
|
-
describe "for a %r-delimited regex literal" do
|
61
|
-
it "works for the simple case with escape sequences" do
|
62
|
-
_('%r[foo\nbar]')
|
63
|
-
.must_be_parsed_as s(:lit, /foo\nbar/)
|
64
|
-
end
|
65
|
-
|
66
|
-
it "works with odd delimiters and escape sequences" do
|
67
|
-
_('%r_foo\nbar_')
|
68
|
-
.must_be_parsed_as s(:lit, /foo\nbar/)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
describe "with interpolations" do
|
73
|
-
it "works for a simple interpolation" do
|
74
|
-
_('/foo#{bar}baz/')
|
75
|
-
.must_be_parsed_as s(:dregx,
|
76
|
-
"foo",
|
77
|
-
s(:evstr, s(:call, nil, :bar)),
|
78
|
-
s(:str, "baz"))
|
79
|
-
end
|
80
|
-
|
81
|
-
it "works for a regex literal with flags and interpolation" do
|
82
|
-
_('/foo#{bar}/ixm')
|
83
|
-
.must_be_parsed_as s(:dregx,
|
84
|
-
"foo",
|
85
|
-
s(:evstr, s(:call, nil, :bar)),
|
86
|
-
7)
|
87
|
-
end
|
88
|
-
|
89
|
-
it "works with the no-encoding flag" do
|
90
|
-
_('/foo#{bar}/n')
|
91
|
-
.must_be_parsed_as s(:dregx,
|
92
|
-
"foo",
|
93
|
-
s(:evstr,
|
94
|
-
s(:call, nil, :bar)), 32)
|
95
|
-
end
|
96
|
-
|
97
|
-
it "works with the unicode-encoding flag" do
|
98
|
-
_('/foo#{bar}/u')
|
99
|
-
.must_be_parsed_as s(:dregx,
|
100
|
-
"foo",
|
101
|
-
s(:evstr,
|
102
|
-
s(:call, nil, :bar)), 16)
|
103
|
-
end
|
104
|
-
|
105
|
-
it "works with unicode flag plus other flag" do
|
106
|
-
_('/foo#{bar}/un')
|
107
|
-
.must_be_parsed_as s(:dregx,
|
108
|
-
"foo",
|
109
|
-
s(:evstr,
|
110
|
-
s(:call, nil, :bar)), 48)
|
111
|
-
end
|
112
|
-
|
113
|
-
it "works with the euc-encoding flag" do
|
114
|
-
_('/foo#{bar}/e')
|
115
|
-
.must_be_parsed_as s(:dregx,
|
116
|
-
"foo",
|
117
|
-
s(:evstr,
|
118
|
-
s(:call, nil, :bar)), 16)
|
119
|
-
end
|
120
|
-
|
121
|
-
it "works with the sjis-encoding flag" do
|
122
|
-
_('/foo#{bar}/s')
|
123
|
-
.must_be_parsed_as s(:dregx,
|
124
|
-
"foo",
|
125
|
-
s(:evstr,
|
126
|
-
s(:call, nil, :bar)), 16)
|
127
|
-
end
|
128
|
-
|
129
|
-
it "works for a regex literal with interpolate-once flag" do
|
130
|
-
_('/foo#{bar}/o')
|
131
|
-
.must_be_parsed_as s(:dregx_once,
|
132
|
-
"foo",
|
133
|
-
s(:evstr, s(:call, nil, :bar)))
|
134
|
-
end
|
135
|
-
|
136
|
-
it "works with an empty interpolation" do
|
137
|
-
_('/foo#{}bar/')
|
138
|
-
.must_be_parsed_as s(:dregx,
|
139
|
-
"foo",
|
140
|
-
s(:evstr),
|
141
|
-
s(:str, "bar"))
|
142
|
-
end
|
143
|
-
|
144
|
-
describe "containing just a literal string" do
|
145
|
-
it "performs the interpolation when it is at the end" do
|
146
|
-
_('/foo#{"bar"}/').must_be_parsed_as s(:lit, /foobar/)
|
147
|
-
end
|
148
|
-
|
149
|
-
it "performs the interpolation when it is in the middle" do
|
150
|
-
_('/foo#{"bar"}baz/').must_be_parsed_as s(:lit, /foobarbaz/)
|
151
|
-
end
|
152
|
-
|
153
|
-
it "performs the interpolation when it is at the start" do
|
154
|
-
_('/#{"foo"}bar/').must_be_parsed_as s(:lit, /foobar/)
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
describe "for string literals" do
|
161
|
-
it "works for empty strings" do
|
162
|
-
_("''")
|
163
|
-
.must_be_parsed_as s(:str, "")
|
164
|
-
end
|
165
|
-
|
166
|
-
it "sets the encoding for literal strings to utf8 even if ascii would do" do
|
167
|
-
parser = RipperRubyParser::Parser.new
|
168
|
-
result = parser.parse '"foo"'
|
169
|
-
_(result).must_equal s(:str, "foo")
|
170
|
-
_(result[1].encoding.to_s).must_equal "UTF-8"
|
171
|
-
end
|
172
|
-
|
173
|
-
it "handles line breaks within double-quoted strings" do
|
174
|
-
_("\"foo\nbar\"")
|
175
|
-
.must_be_parsed_as s(:str, "foo\nbar")
|
176
|
-
end
|
177
|
-
|
178
|
-
it "handles line continuation with double-quoted strings" do
|
179
|
-
_("\"foo\\\nbar\"")
|
180
|
-
.must_be_parsed_as s(:str, "foobar")
|
181
|
-
end
|
182
|
-
|
183
|
-
it "escapes line continuation with double-quoted strings" do
|
184
|
-
_("\"foo\\\\\nbar\"")
|
185
|
-
.must_be_parsed_as s(:str, "foo\\\nbar")
|
186
|
-
end
|
187
|
-
|
188
|
-
describe "with double-quoted strings with escape sequences" do
|
189
|
-
it "works for strings with escape sequences" do
|
190
|
-
_('"\\n"')
|
191
|
-
.must_be_parsed_as s(:str, "\n")
|
192
|
-
end
|
193
|
-
|
194
|
-
it "works for strings with useless escape sequences" do
|
195
|
-
_('"F\\OO"')
|
196
|
-
.must_be_parsed_as s(:str, "FOO")
|
197
|
-
end
|
198
|
-
|
199
|
-
it "works for strings with escaped backslashes" do
|
200
|
-
_('"\\\\n"')
|
201
|
-
.must_be_parsed_as s(:str, '\\n')
|
202
|
-
end
|
203
|
-
|
204
|
-
it "works for a representation of a regex literal with escaped right parenthesis" do
|
205
|
-
_('"/\\\\)/"')
|
206
|
-
.must_be_parsed_as s(:str, '/\\)/')
|
207
|
-
end
|
208
|
-
|
209
|
-
it "works for a uselessly escaped right parenthesis" do
|
210
|
-
_('"/\\)/"')
|
211
|
-
.must_be_parsed_as s(:str, "/)/")
|
212
|
-
end
|
213
|
-
|
214
|
-
it "works for a string containing escaped quotes" do
|
215
|
-
_('"\\""')
|
216
|
-
.must_be_parsed_as s(:str, '"')
|
217
|
-
end
|
218
|
-
|
219
|
-
it "works with hex escapes" do
|
220
|
-
_('"\\x36"').must_be_parsed_as s(:str, "6")
|
221
|
-
_('"\\x4a"').must_be_parsed_as s(:str, "J")
|
222
|
-
_('"\\x4A"').must_be_parsed_as s(:str, "J")
|
223
|
-
_('"\\x3Z"').must_be_parsed_as s(:str, "\x03Z")
|
224
|
-
end
|
225
|
-
|
226
|
-
it "works with single-letter escapes" do
|
227
|
-
_('"foo\\abar"').must_be_parsed_as s(:str, "foo\abar")
|
228
|
-
_('"foo\\bbar"').must_be_parsed_as s(:str, "foo\bbar")
|
229
|
-
_('"foo\\ebar"').must_be_parsed_as s(:str, "foo\ebar")
|
230
|
-
_('"foo\\fbar"').must_be_parsed_as s(:str, "foo\fbar")
|
231
|
-
_('"foo\\nbar"').must_be_parsed_as s(:str, "foo\nbar")
|
232
|
-
_('"foo\\rbar"').must_be_parsed_as s(:str, "foo\rbar")
|
233
|
-
_('"foo\\sbar"').must_be_parsed_as s(:str, "foo\sbar")
|
234
|
-
_('"foo\\tbar"').must_be_parsed_as s(:str, "foo\tbar")
|
235
|
-
_('"foo\\vbar"').must_be_parsed_as s(:str, "foo\vbar")
|
236
|
-
end
|
237
|
-
|
238
|
-
it "works with octal number escapes" do
|
239
|
-
_('"foo\\123bar"').must_be_parsed_as s(:str, "foo\123bar")
|
240
|
-
_('"foo\\23bar"').must_be_parsed_as s(:str, "foo\023bar")
|
241
|
-
_('"foo\\3bar"').must_be_parsed_as s(:str, "foo\003bar")
|
242
|
-
|
243
|
-
_('"foo\\118bar"').must_be_parsed_as s(:str, "foo\0118bar")
|
244
|
-
_('"foo\\18bar"').must_be_parsed_as s(:str, "foo\0018bar")
|
245
|
-
end
|
246
|
-
|
247
|
-
it "works with simple short hand control sequence escapes" do
|
248
|
-
_('"foo\\cabar"').must_be_parsed_as s(:str, "foo\cabar")
|
249
|
-
_('"foo\\cZbar"').must_be_parsed_as s(:str, "foo\cZbar")
|
250
|
-
end
|
251
|
-
|
252
|
-
it "works with simple regular control sequence escapes" do
|
253
|
-
_('"foo\\C-abar"').must_be_parsed_as s(:str, "foo\C-abar")
|
254
|
-
_('"foo\\C-Zbar"').must_be_parsed_as s(:str, "foo\C-Zbar")
|
255
|
-
end
|
256
|
-
|
257
|
-
it "works with unicode escapes" do
|
258
|
-
_('"foo\\u273bbar"').must_be_parsed_as s(:str, "foo✻bar")
|
259
|
-
end
|
260
|
-
|
261
|
-
it "works with unicode escapes with braces" do
|
262
|
-
_('"foo\\u{273b}bar"').must_be_parsed_as s(:str, "foo✻bar")
|
263
|
-
end
|
264
|
-
|
265
|
-
it "works with unicode escapes with braces with 5 hex chars" do
|
266
|
-
_('"foo\\u{101D1}bar"').must_be_parsed_as s(:str, "foo𐇑bar")
|
267
|
-
end
|
268
|
-
|
269
|
-
it "works with unicode escapes with braces with 6 hex chars" do
|
270
|
-
_('"foo\\u{10FFFF}bar"').must_be_parsed_as s(:str, "foo\u{10FFFF}bar")
|
271
|
-
end
|
272
|
-
|
273
|
-
it "converts to unicode if possible" do
|
274
|
-
_('"2\302\275"').must_be_parsed_as s(:str, "2½")
|
275
|
-
end
|
276
|
-
|
277
|
-
it "does not convert to unicode if result is not valid" do
|
278
|
-
_('"2\x82\302\275"')
|
279
|
-
.must_be_parsed_as s(:str,
|
280
|
-
(+"2\x82\xC2\xBD").force_encoding("ascii-8bit"))
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
describe "with interpolations containing just a literal string" do
|
285
|
-
it "performs the interpolation when it is at the end" do
|
286
|
-
_('"foo#{"bar"}"').must_be_parsed_as s(:str, "foobar")
|
287
|
-
end
|
288
|
-
|
289
|
-
it "performs the interpolation when it is in the middle" do
|
290
|
-
_('"foo#{"bar"}baz"').must_be_parsed_as s(:str, "foobarbaz")
|
291
|
-
end
|
292
|
-
|
293
|
-
it "performs the interpolation when it is at the start" do
|
294
|
-
_('"#{"foo"}bar"').must_be_parsed_as s(:str, "foobar")
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
describe "with interpolations without braces" do
|
299
|
-
it "works for ivars" do
|
300
|
-
_("\"foo\#@bar\"").must_be_parsed_as s(:dstr,
|
301
|
-
"foo",
|
302
|
-
s(:evstr, s(:ivar, :@bar)))
|
303
|
-
end
|
304
|
-
|
305
|
-
it "works for gvars" do
|
306
|
-
_("\"foo\#$bar\"").must_be_parsed_as s(:dstr,
|
307
|
-
"foo",
|
308
|
-
s(:evstr, s(:gvar, :$bar)))
|
309
|
-
end
|
310
|
-
|
311
|
-
it "works for cvars" do
|
312
|
-
_("\"foo\#@@bar\"").must_be_parsed_as s(:dstr,
|
313
|
-
"foo",
|
314
|
-
s(:evstr, s(:cvar, :@@bar)))
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
describe "with interpolations with braces" do
|
319
|
-
it "works for trivial interpolated strings" do
|
320
|
-
_('"#{foo}"')
|
321
|
-
.must_be_parsed_as s(:dstr,
|
322
|
-
"",
|
323
|
-
s(:evstr,
|
324
|
-
s(:call, nil, :foo)))
|
325
|
-
end
|
326
|
-
|
327
|
-
it "works for basic interpolated strings" do
|
328
|
-
_('"foo#{bar}"')
|
329
|
-
.must_be_parsed_as s(:dstr,
|
330
|
-
"foo",
|
331
|
-
s(:evstr,
|
332
|
-
s(:call, nil, :bar)))
|
333
|
-
end
|
334
|
-
|
335
|
-
it "works for strings with several interpolations" do
|
336
|
-
_('"foo#{bar}baz#{qux}"')
|
337
|
-
.must_be_parsed_as s(:dstr,
|
338
|
-
"foo",
|
339
|
-
s(:evstr, s(:call, nil, :bar)),
|
340
|
-
s(:str, "baz"),
|
341
|
-
s(:evstr, s(:call, nil, :qux)))
|
342
|
-
end
|
343
|
-
|
344
|
-
it "correctly handles two interpolations in a row" do
|
345
|
-
_("\"\#{bar}\#{qux}\"")
|
346
|
-
.must_be_parsed_as s(:dstr,
|
347
|
-
"",
|
348
|
-
s(:evstr, s(:call, nil, :bar)),
|
349
|
-
s(:evstr, s(:call, nil, :qux)))
|
350
|
-
end
|
351
|
-
|
352
|
-
it "works with an empty interpolation" do
|
353
|
-
_("\"foo\#{}bar\"")
|
354
|
-
.must_be_parsed_as s(:dstr,
|
355
|
-
"foo",
|
356
|
-
s(:evstr),
|
357
|
-
s(:str, "bar"))
|
358
|
-
end
|
359
|
-
|
360
|
-
it "correctly handles interpolation with __FILE__ before another interpolation" do
|
361
|
-
_("\"foo\#{__FILE__}\#{bar}\"")
|
362
|
-
.must_be_parsed_as s(:dstr,
|
363
|
-
"foo(string)",
|
364
|
-
s(:evstr, s(:call, nil, :bar)))
|
365
|
-
end
|
366
|
-
|
367
|
-
it "correctly handles interpolation with __FILE__ after another interpolation" do
|
368
|
-
_("\"\#{bar}foo\#{__FILE__}\"")
|
369
|
-
.must_be_parsed_as s(:dstr,
|
370
|
-
"",
|
371
|
-
s(:evstr, s(:call, nil, :bar)),
|
372
|
-
s(:str, "foo"),
|
373
|
-
s(:str, "(string)"))
|
374
|
-
end
|
375
|
-
|
376
|
-
it "correctly handles nested interpolation" do
|
377
|
-
_('"foo#{"bar#{baz}"}"')
|
378
|
-
.must_be_parsed_as s(:dstr,
|
379
|
-
"foobar",
|
380
|
-
s(:evstr, s(:call, nil, :baz)))
|
381
|
-
end
|
382
|
-
|
383
|
-
it "correctly handles consecutive nested interpolation" do
|
384
|
-
_('"foo#{"bar#{baz}"}foo#{"bar#{baz}"}"')
|
385
|
-
.must_be_parsed_as s(:dstr,
|
386
|
-
"foobar",
|
387
|
-
s(:evstr, s(:call, nil, :baz)),
|
388
|
-
s(:str, "foo"),
|
389
|
-
s(:str, "bar"),
|
390
|
-
s(:evstr, s(:call, nil, :baz)))
|
391
|
-
end
|
392
|
-
end
|
393
|
-
|
394
|
-
describe "with interpolations and escape sequences" do
|
395
|
-
it "works when interpolations are followed by escape sequences" do
|
396
|
-
_('"#{foo}\\n"')
|
397
|
-
.must_be_parsed_as s(:dstr,
|
398
|
-
"",
|
399
|
-
s(:evstr, s(:call, nil, :foo)),
|
400
|
-
s(:str, "\n"))
|
401
|
-
end
|
402
|
-
|
403
|
-
it "works when interpolations contain a mix of other string-like literals" do
|
404
|
-
_('"#{[:foo, \'bar\']}\\n"')
|
405
|
-
.must_be_parsed_as s(:dstr,
|
406
|
-
"",
|
407
|
-
s(:evstr, s(:array, s(:lit, :foo), s(:str, "bar"))),
|
408
|
-
s(:str, "\n"))
|
409
|
-
end
|
410
|
-
|
411
|
-
it "converts to unicode after interpolation" do
|
412
|
-
_('"#{foo}2\302\275"')
|
413
|
-
.must_be_parsed_as s(:dstr,
|
414
|
-
"",
|
415
|
-
s(:evstr, s(:call, nil, :foo)),
|
416
|
-
s(:str, "2½"))
|
417
|
-
end
|
418
|
-
|
419
|
-
it "convert single null byte to unicode after interpolation" do
|
420
|
-
_('"#{foo}\0"')
|
421
|
-
.must_be_parsed_as s(:dstr,
|
422
|
-
"",
|
423
|
-
s(:evstr, s(:call, nil, :foo)),
|
424
|
-
s(:str, "\u0000"))
|
425
|
-
end
|
426
|
-
|
427
|
-
it "converts string with null to unicode after interpolation" do
|
428
|
-
_('"#{foo}bar\0"')
|
429
|
-
.must_be_parsed_as s(:dstr,
|
430
|
-
"",
|
431
|
-
s(:evstr, s(:call, nil, :foo)),
|
432
|
-
s(:str, "bar\x00"))
|
433
|
-
end
|
434
|
-
end
|
435
|
-
|
436
|
-
describe "with single quoted strings" do
|
437
|
-
it "works with escaped single quotes" do
|
438
|
-
_("'foo\\'bar'")
|
439
|
-
.must_be_parsed_as s(:str, "foo'bar")
|
440
|
-
end
|
441
|
-
|
442
|
-
it "works with embedded backslashes" do
|
443
|
-
_("'foo\\abar'")
|
444
|
-
.must_be_parsed_as s(:str, 'foo\abar')
|
445
|
-
end
|
446
|
-
|
447
|
-
it "works with escaped embedded backslashes" do
|
448
|
-
_("'foo\\\\abar'")
|
449
|
-
.must_be_parsed_as s(:str, 'foo\abar')
|
450
|
-
end
|
451
|
-
|
452
|
-
it "works with sequences of backslashes" do
|
453
|
-
_("'foo\\\\\\abar'")
|
454
|
-
.must_be_parsed_as s(:str, 'foo\\\\abar')
|
455
|
-
end
|
456
|
-
|
457
|
-
it "does not process line continuation" do
|
458
|
-
_("'foo\\\nbar'")
|
459
|
-
.must_be_parsed_as s(:str, "foo\\\nbar")
|
460
|
-
end
|
461
|
-
end
|
462
|
-
|
463
|
-
describe "with %Q-delimited strings" do
|
464
|
-
it "works for the simple case" do
|
465
|
-
_("%Q[bar]")
|
466
|
-
.must_be_parsed_as s(:str, "bar")
|
467
|
-
end
|
468
|
-
|
469
|
-
it "works for escape sequences" do
|
470
|
-
_('%Q[foo\\nbar]')
|
471
|
-
.must_be_parsed_as s(:str, "foo\nbar")
|
472
|
-
end
|
473
|
-
|
474
|
-
it "works for multi-line strings" do
|
475
|
-
_("%Q[foo\nbar]")
|
476
|
-
.must_be_parsed_as s(:str, "foo\nbar")
|
477
|
-
end
|
478
|
-
|
479
|
-
it "handles line continuation" do
|
480
|
-
_("%Q[foo\\\nbar]")
|
481
|
-
.must_be_parsed_as s(:str, "foobar")
|
482
|
-
end
|
483
|
-
end
|
484
|
-
|
485
|
-
describe "with %q-delimited strings" do
|
486
|
-
it "works for the simple case" do
|
487
|
-
_("%q[bar]")
|
488
|
-
.must_be_parsed_as s(:str, "bar")
|
489
|
-
end
|
490
|
-
|
491
|
-
it "does not handle for escape sequences" do
|
492
|
-
_('%q[foo\\nbar]')
|
493
|
-
.must_be_parsed_as s(:str, 'foo\nbar')
|
494
|
-
end
|
495
|
-
|
496
|
-
it "works for multi-line strings" do
|
497
|
-
_("%q[foo\nbar]")
|
498
|
-
.must_be_parsed_as s(:str, "foo\nbar")
|
499
|
-
end
|
500
|
-
|
501
|
-
it "handles line continuation" do
|
502
|
-
_("%q[foo\\\nbar]")
|
503
|
-
.must_be_parsed_as s(:str, "foo\\\nbar")
|
504
|
-
end
|
505
|
-
end
|
506
|
-
|
507
|
-
describe "with %-delimited strings" do
|
508
|
-
it "works for the simple case" do
|
509
|
-
_("%(bar)")
|
510
|
-
.must_be_parsed_as s(:str, "bar")
|
511
|
-
end
|
512
|
-
|
513
|
-
it "works for escape sequences" do
|
514
|
-
_('%(foo\nbar)')
|
515
|
-
.must_be_parsed_as s(:str, "foo\nbar")
|
516
|
-
end
|
517
|
-
|
518
|
-
it "works for multiple lines" do
|
519
|
-
_("%(foo\nbar)")
|
520
|
-
.must_be_parsed_as s(:str, "foo\nbar")
|
521
|
-
end
|
522
|
-
|
523
|
-
it "works with line continuations" do
|
524
|
-
_("%(foo\\\nbar)")
|
525
|
-
.must_be_parsed_as s(:str, "foobar")
|
526
|
-
end
|
527
|
-
|
528
|
-
it "works for odd delimiters" do
|
529
|
-
_('%!foo\nbar!')
|
530
|
-
.must_be_parsed_as s(:str, "foo\nbar")
|
531
|
-
end
|
532
|
-
end
|
533
|
-
|
534
|
-
describe "with string concatenation" do
|
535
|
-
it "performs the concatenation in the case of two simple literal strings" do
|
536
|
-
_('"foo" "bar"').must_be_parsed_as s(:str, "foobar")
|
537
|
-
end
|
538
|
-
|
539
|
-
it "performs the concatenation when the right string has interpolations" do
|
540
|
-
_("\"foo\" \"bar\#{baz}\"")
|
541
|
-
.must_be_parsed_as s(:dstr,
|
542
|
-
"foobar",
|
543
|
-
s(:evstr, s(:call, nil, :baz)))
|
544
|
-
end
|
545
|
-
|
546
|
-
describe "when the left string has interpolations" do
|
547
|
-
it "performs the concatenation" do
|
548
|
-
_("\"foo\#{bar}\" \"baz\"")
|
549
|
-
.must_be_parsed_as s(:dstr,
|
550
|
-
"foo",
|
551
|
-
s(:evstr, s(:call, nil, :bar)),
|
552
|
-
s(:str, "baz"))
|
553
|
-
end
|
554
|
-
|
555
|
-
it "performs the concatenation with an empty string" do
|
556
|
-
_("\"foo\#{bar}\" \"\"")
|
557
|
-
.must_be_parsed_as s(:dstr,
|
558
|
-
"foo",
|
559
|
-
s(:evstr, s(:call, nil, :bar)),
|
560
|
-
s(:str, ""))
|
561
|
-
end
|
562
|
-
end
|
563
|
-
|
564
|
-
describe "when both strings have interpolations" do
|
565
|
-
it "performs the concatenation" do
|
566
|
-
_("\"foo\#{bar}\" \"baz\#{qux}\"")
|
567
|
-
.must_be_parsed_as s(:dstr,
|
568
|
-
"foo",
|
569
|
-
s(:evstr, s(:call, nil, :bar)),
|
570
|
-
s(:str, "baz"),
|
571
|
-
s(:evstr, s(:call, nil, :qux)))
|
572
|
-
end
|
573
|
-
|
574
|
-
it "removes empty substrings from the concatenation" do
|
575
|
-
_("\"foo\#{bar}\" \"\#{qux}\"")
|
576
|
-
.must_be_parsed_as s(:dstr,
|
577
|
-
"foo",
|
578
|
-
s(:evstr, s(:call, nil, :bar)),
|
579
|
-
s(:evstr, s(:call, nil, :qux)))
|
580
|
-
end
|
581
|
-
end
|
582
|
-
end
|
583
|
-
|
584
|
-
describe "for heredocs" do
|
585
|
-
it "works for the simple case" do
|
586
|
-
_("<<FOO\nbar\nFOO")
|
587
|
-
.must_be_parsed_as s(:str, "bar\n")
|
588
|
-
end
|
589
|
-
|
590
|
-
it "works with multiple lines" do
|
591
|
-
_("<<FOO\nbar\nbaz\nFOO")
|
592
|
-
.must_be_parsed_as s(:str, "bar\nbaz\n")
|
593
|
-
end
|
594
|
-
|
595
|
-
it "works for the indentable case" do
|
596
|
-
_("<<-FOO\n bar\n FOO")
|
597
|
-
.must_be_parsed_as s(:str, " bar\n")
|
598
|
-
end
|
599
|
-
|
600
|
-
it "works for the automatically outdenting case" do
|
601
|
-
_(" <<~FOO\n bar\n FOO")
|
602
|
-
.must_be_parsed_as s(:str, "bar\n")
|
603
|
-
end
|
604
|
-
|
605
|
-
it "works for escape sequences" do
|
606
|
-
_("<<FOO\nbar\\tbaz\nFOO")
|
607
|
-
.must_be_parsed_as s(:str, "bar\tbaz\n")
|
608
|
-
end
|
609
|
-
|
610
|
-
it 'converts \r to carriage returns' do
|
611
|
-
_("<<FOO\nbar\\rbaz\\r\nFOO")
|
612
|
-
.must_be_parsed_as s(:str, "bar\rbaz\r\n")
|
613
|
-
end
|
614
|
-
|
615
|
-
it "does not unescape with single quoted version" do
|
616
|
-
_("<<'FOO'\nbar\\tbaz\nFOO")
|
617
|
-
.must_be_parsed_as s(:str, "bar\\tbaz\n")
|
618
|
-
end
|
619
|
-
|
620
|
-
it "works with multiple lines with the single quoted version" do
|
621
|
-
_("<<'FOO'\nbar\nbaz\nFOO")
|
622
|
-
.must_be_parsed_as s(:str, "bar\nbaz\n")
|
623
|
-
end
|
624
|
-
|
625
|
-
it "does not unescape with indentable single quoted version" do
|
626
|
-
_("<<-'FOO'\n bar\\tbaz\n FOO")
|
627
|
-
.must_be_parsed_as s(:str, " bar\\tbaz\n")
|
628
|
-
end
|
629
|
-
|
630
|
-
it "does not unescape the automatically outdenting single quoted version" do
|
631
|
-
_("<<~'FOO'\n bar\\tbaz\n FOO")
|
632
|
-
.must_be_parsed_as s(:str, "bar\\tbaz\n")
|
633
|
-
end
|
634
|
-
|
635
|
-
it "handles line continuation" do
|
636
|
-
_("<<FOO\nbar\\\nbaz\nFOO")
|
637
|
-
.must_be_parsed_as s(:str, "barbaz\n")
|
638
|
-
end
|
639
|
-
|
640
|
-
it "escapes line continuation" do
|
641
|
-
_("<<FOO\nbar\\\\\nbaz\nFOO")
|
642
|
-
.must_be_parsed_as s(:str, "bar\\\nbaz\n")
|
643
|
-
end
|
644
|
-
|
645
|
-
it "converts to unicode" do
|
646
|
-
_("<<FOO\n2\\302\\275\nFOO")
|
647
|
-
.must_be_parsed_as s(:str, "2½\n")
|
648
|
-
end
|
649
|
-
|
650
|
-
it "handles interpolation" do
|
651
|
-
_("<<FOO\n\#{bar}\nFOO")
|
652
|
-
.must_be_parsed_as s(:dstr, "",
|
653
|
-
s(:evstr, s(:call, nil, :bar)),
|
654
|
-
s(:str, "\n"))
|
655
|
-
end
|
656
|
-
|
657
|
-
it "handles line continuation after interpolation" do
|
658
|
-
_("<<FOO\n\#{bar}\nbaz\\\nqux\nFOO")
|
659
|
-
.must_be_parsed_as s(:dstr, "",
|
660
|
-
s(:evstr, s(:call, nil, :bar)),
|
661
|
-
s(:str, "\nbazqux\n"))
|
662
|
-
end
|
663
|
-
|
664
|
-
it "handles line continuation after interpolation for the indentable case" do
|
665
|
-
_("<<-FOO\n\#{bar}\nbaz\\\nqux\nFOO")
|
666
|
-
.must_be_parsed_as s(:dstr, "",
|
667
|
-
s(:evstr, s(:call, nil, :bar)),
|
668
|
-
s(:str, "\nbazqux\n"))
|
669
|
-
end
|
670
|
-
end
|
671
|
-
end
|
672
|
-
|
673
|
-
describe "for word list literals with %w delimiter" do
|
674
|
-
it "works for the simple case" do
|
675
|
-
_("%w(foo bar)")
|
676
|
-
.must_be_parsed_as s(:array, s(:str, "foo"), s(:str, "bar"))
|
677
|
-
end
|
678
|
-
|
679
|
-
it "does not perform interpolation" do
|
680
|
-
_('%w(foo\\nbar baz)')
|
681
|
-
.must_be_parsed_as s(:array, s(:str, 'foo\\nbar'), s(:str, "baz"))
|
682
|
-
end
|
683
|
-
|
684
|
-
it "handles line continuation" do
|
685
|
-
_("%w(foo\\\nbar baz)")
|
686
|
-
.must_be_parsed_as s(:array, s(:str, "foo\nbar"), s(:str, "baz"))
|
687
|
-
end
|
688
|
-
|
689
|
-
it "handles escaped spaces" do
|
690
|
-
_('%w(foo bar\ baz)')
|
691
|
-
.must_be_parsed_as s(:array, s(:str, "foo"), s(:str, "bar baz"))
|
692
|
-
end
|
693
|
-
end
|
694
|
-
|
695
|
-
describe "for word list literals with %W delimiter" do
|
696
|
-
it "works for the simple case" do
|
697
|
-
_("%W(foo bar)")
|
698
|
-
.must_be_parsed_as s(:array, s(:str, "foo"), s(:str, "bar"))
|
699
|
-
end
|
700
|
-
|
701
|
-
it "handles escaped spaces" do
|
702
|
-
_('%W(foo bar\ baz)')
|
703
|
-
.must_be_parsed_as s(:array, s(:str, "foo"), s(:str, "bar baz"))
|
704
|
-
end
|
705
|
-
|
706
|
-
it "correctly handles interpolation" do
|
707
|
-
_("%W(foo \#{bar} baz)")
|
708
|
-
.must_be_parsed_as s(:array,
|
709
|
-
s(:str, "foo"),
|
710
|
-
s(:dstr, "", s(:evstr, s(:call, nil, :bar))),
|
711
|
-
s(:str, "baz"))
|
712
|
-
end
|
713
|
-
|
714
|
-
it "correctly handles braceless interpolation" do
|
715
|
-
_("%W(foo \#@bar baz)")
|
716
|
-
.must_be_parsed_as s(:array,
|
717
|
-
s(:str, "foo"),
|
718
|
-
s(:dstr, "", s(:evstr, s(:ivar, :@bar))),
|
719
|
-
s(:str, "baz"))
|
720
|
-
end
|
721
|
-
|
722
|
-
it "correctly handles in-word interpolation" do
|
723
|
-
_("%W(foo \#{bar}baz)")
|
724
|
-
.must_be_parsed_as s(:array,
|
725
|
-
s(:str, "foo"),
|
726
|
-
s(:dstr,
|
727
|
-
"",
|
728
|
-
s(:evstr, s(:call, nil, :bar)),
|
729
|
-
s(:str, "baz")))
|
730
|
-
end
|
731
|
-
|
732
|
-
it "correctly handles escape sequences" do
|
733
|
-
_('%W(foo\nbar baz)')
|
734
|
-
.must_be_parsed_as s(:array,
|
735
|
-
s(:str, "foo\nbar"),
|
736
|
-
s(:str, "baz"))
|
737
|
-
end
|
738
|
-
|
739
|
-
it "converts to unicode if possible" do
|
740
|
-
_('%W(2\302\275)').must_be_parsed_as s(:array, s(:str, "2½"))
|
741
|
-
end
|
742
|
-
|
743
|
-
it "correctly handles line continuation" do
|
744
|
-
_("%W(foo\\\nbar baz)")
|
745
|
-
.must_be_parsed_as s(:array,
|
746
|
-
s(:str, "foo\nbar"),
|
747
|
-
s(:str, "baz"))
|
748
|
-
end
|
749
|
-
|
750
|
-
it "correctly handles multiple lines" do
|
751
|
-
_("%W(foo\nbar baz)")
|
752
|
-
.must_be_parsed_as s(:array,
|
753
|
-
s(:str, "foo"),
|
754
|
-
s(:str, "bar"),
|
755
|
-
s(:str, "baz"))
|
756
|
-
end
|
757
|
-
end
|
758
|
-
|
759
|
-
describe "for symbol list literals with %i delimiter" do
|
760
|
-
it "works for the simple case" do
|
761
|
-
_("%i(foo bar)")
|
762
|
-
.must_be_parsed_as s(:array, s(:lit, :foo), s(:lit, :bar))
|
763
|
-
end
|
764
|
-
|
765
|
-
it "does not perform interpolation" do
|
766
|
-
_('%i(foo\\nbar baz)')
|
767
|
-
.must_be_parsed_as s(:array, s(:lit, :"foo\\nbar"), s(:lit, :baz))
|
768
|
-
end
|
769
|
-
|
770
|
-
it "handles line continuation" do
|
771
|
-
_("%i(foo\\\nbar baz)")
|
772
|
-
.must_be_parsed_as s(:array, s(:lit, :"foo\nbar"), s(:lit, :baz))
|
773
|
-
end
|
774
|
-
end
|
775
|
-
|
776
|
-
describe "for symbol list literals with %I delimiter" do
|
777
|
-
it "works for the simple case" do
|
778
|
-
_("%I(foo bar)")
|
779
|
-
.must_be_parsed_as s(:array, s(:lit, :foo), s(:lit, :bar))
|
780
|
-
end
|
781
|
-
|
782
|
-
it "correctly handles escape sequences" do
|
783
|
-
_('%I(foo\nbar baz)')
|
784
|
-
.must_be_parsed_as s(:array,
|
785
|
-
s(:lit, :"foo\nbar"),
|
786
|
-
s(:lit, :baz))
|
787
|
-
end
|
788
|
-
|
789
|
-
it "correctly handles interpolation" do
|
790
|
-
_("%I(foo \#{bar} baz)")
|
791
|
-
.must_be_parsed_as s(:array,
|
792
|
-
s(:lit, :foo),
|
793
|
-
s(:dsym, "", s(:evstr, s(:call, nil, :bar))),
|
794
|
-
s(:lit, :baz))
|
795
|
-
end
|
796
|
-
|
797
|
-
it "correctly handles in-word interpolation" do
|
798
|
-
_("%I(foo \#{bar}baz)")
|
799
|
-
.must_be_parsed_as s(:array,
|
800
|
-
s(:lit, :foo),
|
801
|
-
s(:dsym,
|
802
|
-
"",
|
803
|
-
s(:evstr, s(:call, nil, :bar)),
|
804
|
-
s(:str, "baz")))
|
805
|
-
end
|
806
|
-
|
807
|
-
it "correctly handles line continuation" do
|
808
|
-
_("%I(foo\\\nbar baz)")
|
809
|
-
.must_be_parsed_as s(:array,
|
810
|
-
s(:lit, :"foo\nbar"),
|
811
|
-
s(:lit, :baz))
|
812
|
-
end
|
813
|
-
|
814
|
-
it "correctly handles multiple lines" do
|
815
|
-
_("%I(foo\nbar baz)")
|
816
|
-
.must_be_parsed_as s(:array,
|
817
|
-
s(:lit, :foo),
|
818
|
-
s(:lit, :bar),
|
819
|
-
s(:lit, :baz))
|
820
|
-
end
|
821
|
-
end
|
822
|
-
|
823
9
|
describe "for character literals" do
|
824
10
|
it "works for simple character literals" do
|
825
11
|
_("?a")
|
@@ -862,146 +48,6 @@ describe RipperRubyParser::Parser do
|
|
862
48
|
end
|
863
49
|
end
|
864
50
|
|
865
|
-
describe "for symbol literals" do
|
866
|
-
it "works for simple symbols" do
|
867
|
-
_(":foo")
|
868
|
-
.must_be_parsed_as s(:lit, :foo)
|
869
|
-
end
|
870
|
-
|
871
|
-
it "works for symbols that look like instance variable names" do
|
872
|
-
_(":@foo")
|
873
|
-
.must_be_parsed_as s(:lit, :@foo)
|
874
|
-
end
|
875
|
-
|
876
|
-
it "works for symbols that look like class names" do
|
877
|
-
_(":Foo")
|
878
|
-
.must_be_parsed_as s(:lit, :Foo)
|
879
|
-
end
|
880
|
-
|
881
|
-
it "works for symbols that look like keywords" do
|
882
|
-
_(":class").must_be_parsed_as s(:lit, :class)
|
883
|
-
end
|
884
|
-
|
885
|
-
it "works for :__LINE__" do
|
886
|
-
_(":__LINE__")
|
887
|
-
.must_be_parsed_as s(:lit, :__LINE__)
|
888
|
-
end
|
889
|
-
|
890
|
-
it "works for :__FILE__" do
|
891
|
-
_(":__FILE__")
|
892
|
-
.must_be_parsed_as s(:lit, :__FILE__)
|
893
|
-
end
|
894
|
-
|
895
|
-
it "works for a backtick symbol" do
|
896
|
-
_(":`").must_be_parsed_as s(:lit, :`)
|
897
|
-
end
|
898
|
-
|
899
|
-
it "works for simple dsyms" do
|
900
|
-
_(':"foo"')
|
901
|
-
.must_be_parsed_as s(:lit, :foo)
|
902
|
-
end
|
903
|
-
|
904
|
-
it "works for dsyms with interpolations" do
|
905
|
-
_(':"foo#{bar}"')
|
906
|
-
.must_be_parsed_as s(:dsym,
|
907
|
-
"foo",
|
908
|
-
s(:evstr, s(:call, nil, :bar)))
|
909
|
-
end
|
910
|
-
|
911
|
-
it "works for dsyms with interpolations at the start" do
|
912
|
-
_(':"#{bar}"')
|
913
|
-
.must_be_parsed_as s(:dsym,
|
914
|
-
"",
|
915
|
-
s(:evstr, s(:call, nil, :bar)))
|
916
|
-
end
|
917
|
-
|
918
|
-
it "works for dsyms with escape sequences" do
|
919
|
-
_(':"foo\nbar"')
|
920
|
-
.must_be_parsed_as s(:lit, :"foo\nbar")
|
921
|
-
end
|
922
|
-
|
923
|
-
it "works for dsyms with multiple lines" do
|
924
|
-
_(":\"foo\nbar\"")
|
925
|
-
.must_be_parsed_as s(:lit, :"foo\nbar")
|
926
|
-
end
|
927
|
-
|
928
|
-
it "works for dsyms with line continuations" do
|
929
|
-
_(":\"foo\\\nbar\"")
|
930
|
-
.must_be_parsed_as s(:lit, :foobar)
|
931
|
-
end
|
932
|
-
|
933
|
-
it "works with single quoted dsyms" do
|
934
|
-
_(":'foo'")
|
935
|
-
.must_be_parsed_as s(:lit, :foo)
|
936
|
-
end
|
937
|
-
|
938
|
-
it "works with single quoted dsyms with escaped single quotes" do
|
939
|
-
_(":'foo\\'bar'")
|
940
|
-
.must_be_parsed_as s(:lit, :'foo\'bar')
|
941
|
-
end
|
942
|
-
|
943
|
-
it "works with single quoted dsyms with multiple lines" do
|
944
|
-
_(":'foo\nbar'")
|
945
|
-
.must_be_parsed_as s(:lit, :"foo\nbar")
|
946
|
-
end
|
947
|
-
|
948
|
-
it "works with single quoted dsyms with line continuations" do
|
949
|
-
_(":'foo\\\nbar'")
|
950
|
-
.must_be_parsed_as s(:lit, :"foo\\\nbar")
|
951
|
-
end
|
952
|
-
|
953
|
-
it "works with single quoted dsyms with embedded backslashes" do
|
954
|
-
_(":'foo\\abar'")
|
955
|
-
.must_be_parsed_as s(:lit, :"foo\\abar")
|
956
|
-
end
|
957
|
-
|
958
|
-
it "works with barewords that need to be interpreted as symbols" do
|
959
|
-
_("alias foo bar")
|
960
|
-
.must_be_parsed_as s(:alias,
|
961
|
-
s(:lit, :foo), s(:lit, :bar))
|
962
|
-
end
|
963
|
-
|
964
|
-
it "assigns a line number to the result" do
|
965
|
-
result = parser.parse ":foo"
|
966
|
-
_(result.line).must_equal 1
|
967
|
-
end
|
968
|
-
end
|
969
|
-
|
970
|
-
describe "for backtick string literals" do
|
971
|
-
it "works for basic backtick strings" do
|
972
|
-
_("`foo`")
|
973
|
-
.must_be_parsed_as s(:xstr, "foo")
|
974
|
-
end
|
975
|
-
|
976
|
-
it "works for interpolated backtick strings" do
|
977
|
-
_('`foo#{bar}`')
|
978
|
-
.must_be_parsed_as s(:dxstr,
|
979
|
-
"foo",
|
980
|
-
s(:evstr, s(:call, nil, :bar)))
|
981
|
-
end
|
982
|
-
|
983
|
-
it "works for backtick strings interpolated at the start" do
|
984
|
-
_('`#{foo}`')
|
985
|
-
.must_be_parsed_as s(:dxstr, "",
|
986
|
-
s(:evstr, s(:call, nil, :foo)))
|
987
|
-
end
|
988
|
-
|
989
|
-
it "works for backtick strings with escape sequences" do
|
990
|
-
_('`foo\\n`')
|
991
|
-
.must_be_parsed_as s(:xstr, "foo\n")
|
992
|
-
end
|
993
|
-
|
994
|
-
it "works for backtick strings with multiple lines" do
|
995
|
-
_("`foo\nbar`")
|
996
|
-
.must_be_parsed_as s(:xstr, "foo\nbar")
|
997
|
-
end
|
998
|
-
|
999
|
-
it "works for backtick strings with line continuations" do
|
1000
|
-
_("`foo\\\nbar`")
|
1001
|
-
.must_be_parsed_as s(:xstr, "foobar")
|
1002
|
-
end
|
1003
|
-
end
|
1004
|
-
|
1005
51
|
describe "for array literals" do
|
1006
52
|
it "works for an empty array" do
|
1007
53
|
_("[]")
|
@@ -1109,6 +155,11 @@ describe RipperRubyParser::Parser do
|
|
1109
155
|
_("1000r")
|
1110
156
|
.must_be_parsed_as s(:lit, 1000r)
|
1111
157
|
end
|
158
|
+
|
159
|
+
it "works for imaginary numbers" do
|
160
|
+
_("1i")
|
161
|
+
.must_be_parsed_as s(:lit, 1i)
|
162
|
+
end
|
1112
163
|
end
|
1113
164
|
end
|
1114
165
|
end
|