ripper_ruby_parser 1.7.1 → 1.7.2

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