parser 2.6.4.1 → 2.7.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -53,7 +53,7 @@ rule
53
53
  else_t, else_ = val[2]
54
54
  ensure_t, ensure_ = val[3]
55
55
 
56
- if rescue_bodies.empty? && !else_.nil?
56
+ if rescue_bodies.empty? && !else_t.nil?
57
57
  diagnostic :warning, :useless_else, nil, else_t
58
58
  end
59
59
 
@@ -266,7 +266,7 @@ module Parser
266
266
 
267
267
  def combine(range, attributes)
268
268
  range = check_range_validity(range)
269
- action = TreeRewriter::Action.new(range, @enforcer, attributes)
269
+ action = TreeRewriter::Action.new(range, @enforcer, **attributes)
270
270
  @action_root = @action_root.combine(action)
271
271
  self
272
272
  end
@@ -56,11 +56,11 @@ module Parser
56
56
  if action.range == @range
57
57
  merge(action)
58
58
  else
59
- place_in_hierachy(action)
59
+ place_in_hierarchy(action)
60
60
  end
61
61
  end
62
62
 
63
- def place_in_hierachy(action)
63
+ def place_in_hierarchy(action)
64
64
  family = @children.group_by { |child| child.relationship_with(action) }
65
65
 
66
66
  if family[:fusible]
@@ -3,6 +3,8 @@
3
3
  module Parser
4
4
 
5
5
  class StaticEnvironment
6
+ FORWARD_ARGS = :FORWARD_ARGS
7
+
6
8
  def initialize
7
9
  reset
8
10
  end
@@ -41,6 +43,14 @@ module Parser
41
43
  def declared?(name)
42
44
  @variables.include?(name.to_sym)
43
45
  end
46
+
47
+ def declare_forward_args
48
+ declare(FORWARD_ARGS)
49
+ end
50
+
51
+ def declared_forward_args?
52
+ declared?(FORWARD_ARGS)
53
+ end
44
54
  end
45
55
 
46
56
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Parser
4
+
5
+ class VariablesStack
6
+ def initialize
7
+ @stack = []
8
+ push
9
+ end
10
+
11
+ def push
12
+ @stack << Set.new
13
+ end
14
+
15
+ def pop
16
+ @stack.pop
17
+ end
18
+
19
+ def reset
20
+ @stack.clear
21
+ end
22
+
23
+ def declare(name)
24
+ @stack.last << name.to_sym
25
+ end
26
+
27
+ def declared?(name)
28
+ @stack.last.include?(name.to_sym)
29
+ end
30
+ end
31
+
32
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parser
4
- VERSION = '2.6.4.1'
4
+ VERSION = '2.7.0.3'
5
5
  end
data/parser.gemspec CHANGED
@@ -13,6 +13,13 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = 'https://github.com/whitequark/parser'
14
14
  spec.license = 'MIT'
15
15
 
16
+ spec.metadata = {
17
+ 'bug_tracker_uri' => 'https://github.com/whitequark/parser/issues',
18
+ 'changelog_uri' => "https://github.com/whitequark/parser/blob/v#{spec.version}/CHANGELOG.md",
19
+ 'documentation_uri' => "https://www.rubydoc.info/gems/parser/#{spec.version}",
20
+ 'source_code_uri' => "https://github.com/whitequark/parser/tree/v#{spec.version}"
21
+ }
22
+
16
23
  spec.files = `git ls-files`.split + %w(
17
24
  lib/parser/lexer.rb
18
25
  lib/parser/ruby18.rb
data/test/helper.rb CHANGED
@@ -19,6 +19,7 @@ if ENV.include?('COVERAGE') && SimpleCov.usable?
19
19
  ruby24.y
20
20
  ruby25.y
21
21
  ruby26.y
22
+ ruby27.y
22
23
  ),
23
24
  File.expand_path('../../lib/parser', __FILE__))
24
25
 
data/test/parse_helper.rb CHANGED
@@ -127,6 +127,9 @@ module ParseHelper
127
127
 
128
128
  assert parser.instance_eval { @lexer }.cmdarg.empty?,
129
129
  "(#{version}) expected cmdarg to be empty after parsing"
130
+
131
+ assert_equal 0, parser.instance_eval { @lexer.instance_eval { @paren_nest } },
132
+ "(#{version}) expected paren_nest to be 0 after parsing"
130
133
  end
131
134
 
132
135
  # Use like this:
data/test/test_lexer.rb CHANGED
@@ -477,14 +477,18 @@ class TestLexer < Minitest::Test
477
477
  end
478
478
 
479
479
  def test_comment
480
- assert_scanned("1 # one\n# two\n2",
481
- :tINTEGER, 1, [0, 1],
482
- :tNL, nil, [7, 8],
483
- :tINTEGER, 2, [14, 15])
480
+ [26, 27].each do |version|
481
+ setup_lexer(version)
482
+
483
+ assert_scanned("1 # one\n# two\n2",
484
+ :tINTEGER, 1, [0, 1],
485
+ :tNL, nil, [7, 8],
486
+ :tINTEGER, 2, [14, 15])
484
487
 
485
- assert_equal 2, @lex.comments.length
486
- assert_equal '# one', @lex.comments[0].text
487
- assert_equal '# two', @lex.comments[1].text
488
+ assert_equal 2, @lex.comments.length
489
+ assert_equal '# one', @lex.comments[0].text
490
+ assert_equal '# two', @lex.comments[1].text
491
+ end
488
492
  end
489
493
 
490
494
  def test_comment_expr_beg
@@ -1503,6 +1507,13 @@ class TestLexer < Minitest::Test
1503
1507
  assert_scanned "||", :tOROP, "||", [0, 2]
1504
1508
  end
1505
1509
 
1510
+ def test_or2__after_27
1511
+ setup_lexer(27)
1512
+ assert_scanned("||",
1513
+ :tPIPE, "|", [0, 1],
1514
+ :tPIPE, "|", [1, 2])
1515
+ end
1516
+
1506
1517
  def test_or2_equals
1507
1518
  assert_scanned "||=", :tOP_ASGN, "||", [0, 3]
1508
1519
  end
@@ -3558,47 +3569,6 @@ class TestLexer < Minitest::Test
3558
3569
  :tIDENTIFIER, 're', [1, 3])
3559
3570
  end
3560
3571
 
3561
- def test_meth_ref
3562
- assert_scanned('foo.:bar',
3563
- :tIDENTIFIER, 'foo', [0, 3],
3564
- :tMETHREF, '.:', [3, 5],
3565
- :tIDENTIFIER, 'bar', [5, 8])
3566
-
3567
- assert_scanned('foo .:bar',
3568
- :tIDENTIFIER, 'foo', [0, 3],
3569
- :tMETHREF, '.:', [4, 6],
3570
- :tIDENTIFIER, 'bar', [6, 9])
3571
- end
3572
-
3573
- def test_meth_ref_unary_op
3574
- assert_scanned('foo.:+',
3575
- :tIDENTIFIER, 'foo', [0, 3],
3576
- :tMETHREF, '.:', [3, 5],
3577
- :tPLUS, '+', [5, 6])
3578
-
3579
- assert_scanned('foo.:-@',
3580
- :tIDENTIFIER, 'foo', [0, 3],
3581
- :tMETHREF, '.:', [3, 5],
3582
- :tUMINUS, '-@', [5, 7])
3583
- end
3584
-
3585
- def test_meth_ref_unsupported_newlines
3586
- # MRI emits exactly the same sequence of tokens,
3587
- # the error happens later in the parser
3588
-
3589
- assert_scanned('foo. :+',
3590
- :tIDENTIFIER, 'foo', [0, 3],
3591
- :tDOT, '.', [3, 4],
3592
- :tCOLON, ':', [5, 6],
3593
- :tUPLUS, '+', [6, 7])
3594
-
3595
- assert_scanned('foo.: +',
3596
- :tIDENTIFIER, 'foo', [0, 3],
3597
- :tDOT, '.', [3, 4],
3598
- :tCOLON, ':', [4, 5],
3599
- :tPLUS, '+', [6, 7])
3600
- end
3601
-
3602
3572
  def lex_numbered_parameter(input)
3603
3573
  @lex.max_numparam_stack.push
3604
3574
 
@@ -3635,25 +3605,4 @@ class TestLexer < Minitest::Test
3635
3605
  end
3636
3606
  end
3637
3607
 
3638
- def test_numbered_args_before_27
3639
- setup_lexer(26)
3640
- refute_scanned_numbered_parameter('@1')
3641
- end
3642
-
3643
- def test_numbered_args_27
3644
- setup_lexer(27)
3645
- assert_scanned_numbered_parameter('@1')
3646
- assert_equal(@lex.max_numparam, 1)
3647
-
3648
- setup_lexer(27)
3649
- assert_scanned_numbered_parameter('@100')
3650
- assert_equal(@lex.max_numparam, 100)
3651
-
3652
- setup_lexer(27)
3653
- refute_scanned_numbered_parameter('@101', :too_large_numparam)
3654
-
3655
- setup_lexer(27)
3656
- refute_scanned_numbered_parameter('@01', :leading_zero_in_numparam)
3657
- end
3658
-
3659
3608
  end
data/test/test_parser.rb CHANGED
@@ -324,7 +324,7 @@ class TestParser < Minitest::Test
324
324
  assert_parses(
325
325
  s(:send, nil, :p,
326
326
  s(:dstr,
327
- s(:str, "x\n"),
327
+ s(:str, "\tx\n"),
328
328
  s(:str, "y\n"))),
329
329
  %Q{p <<~E\n\tx\n y\nE},
330
330
  %q{},
@@ -432,6 +432,14 @@ class TestParser < Minitest::Test
432
432
  SINCE_2_3)
433
433
  end
434
434
 
435
+ def test_parser_bug_640
436
+ assert_parses(
437
+ s(:str, "bazqux\n"),
438
+ %Q{<<~FOO\n baz\\\n qux\nFOO},
439
+ %q{},
440
+ SINCE_2_3)
441
+ end
442
+
435
443
  # Symbols
436
444
 
437
445
  def test_symbol_plain
@@ -2168,7 +2176,7 @@ class TestParser < Minitest::Test
2168
2176
  s(:lvar, :var)),
2169
2177
  %q{def f(var = defined?(var)) var end},
2170
2178
  %q{},
2171
- SINCE_2_1)
2179
+ SINCE_2_7 - SINCE_2_1)
2172
2180
 
2173
2181
  assert_parses(
2174
2182
  s(:def, :f,
@@ -2176,7 +2184,7 @@ class TestParser < Minitest::Test
2176
2184
  s(:lvar, :var)),
2177
2185
  %q{def f(var: defined?(var)) var end},
2178
2186
  %q{},
2179
- SINCE_2_1)
2187
+ SINCE_2_7 - SINCE_2_1)
2180
2188
 
2181
2189
  assert_parses(
2182
2190
  s(:block,
@@ -2477,7 +2485,7 @@ class TestParser < Minitest::Test
2477
2485
  %Q{|;\na\n|},
2478
2486
  SINCE_2_0)
2479
2487
 
2480
- # tOROP
2488
+ # tOROP before 2.7 / tPIPE+tPIPE after
2481
2489
  assert_parses_blockargs(
2482
2490
  s(:args),
2483
2491
  %q{||})
@@ -5094,6 +5102,12 @@ class TestParser < Minitest::Test
5094
5102
  %q{begin; 1; else; 2; end},
5095
5103
  %q{ ~~~~ location},
5096
5104
  SINCE_2_6)
5105
+
5106
+ assert_diagnoses(
5107
+ [:error, :useless_else],
5108
+ %q{begin; 1; else; end},
5109
+ %q{ ~~~~ location},
5110
+ SINCE_2_6)
5097
5111
  end
5098
5112
 
5099
5113
  def test_ensure
@@ -5668,7 +5682,9 @@ class TestParser < Minitest::Test
5668
5682
  s(:def, :foo, s(:args),
5669
5683
  s(:begin,
5670
5684
  s(:begin, nil))),
5671
- %q{def foo; else; end})
5685
+ %q{def foo; else; end},
5686
+ %q{},
5687
+ ALL_VERSIONS - SINCE_2_6)
5672
5688
  end
5673
5689
 
5674
5690
  def test_bug_heredoc_do
@@ -7206,38 +7222,6 @@ class TestParser < Minitest::Test
7206
7222
  end
7207
7223
  end
7208
7224
 
7209
- def test_meth_ref
7210
- assert_parses(
7211
- s(:meth_ref, s(:lvar, :foo), :bar),
7212
- %q{foo.:bar},
7213
- %q{ ^^ dot
7214
- | ~~~ selector
7215
- |~~~~~~~~ expression},
7216
- SINCE_2_7)
7217
-
7218
- assert_parses(
7219
- s(:meth_ref, s(:lvar, :foo), :+@),
7220
- %q{foo.:+@},
7221
- %q{ ^^ dot
7222
- | ~~ selector
7223
- |~~~~~~~ expression},
7224
- SINCE_2_7)
7225
- end
7226
-
7227
- def test_meth_ref_unsupported_newlines
7228
- assert_diagnoses(
7229
- [:error, :unexpected_token, { :token => 'tCOLON' }],
7230
- %Q{foo. :+},
7231
- %q{ ^ location},
7232
- SINCE_2_7)
7233
-
7234
- assert_diagnoses(
7235
- [:error, :unexpected_token, { :token => 'tCOLON' }],
7236
- %Q{foo.: +},
7237
- %q{ ^ location},
7238
- SINCE_2_7)
7239
- end
7240
-
7241
7225
  def test_unterimated_heredoc_id__27
7242
7226
  assert_diagnoses(
7243
7227
  [:error, :unterminated_heredoc_id],
@@ -7260,44 +7244,35 @@ class TestParser < Minitest::Test
7260
7244
  end
7261
7245
  end
7262
7246
 
7263
- def test_numbered_args_before_27
7264
- assert_diagnoses(
7265
- [:error, :ivar_name, { :name => '@1' }],
7266
- %q{m { @1 }},
7267
- %q{ ^^ location},
7268
- ALL_VERSIONS - SINCE_2_7
7269
- )
7270
- end
7271
-
7272
7247
  def test_numbered_args_after_27
7273
7248
  assert_parses(
7274
7249
  s(:numblock,
7275
7250
  s(:send, nil, :m),
7276
- 15,
7251
+ 9,
7277
7252
  s(:send,
7278
- s(:numparam, 1), :+,
7279
- s(:numparam, 15))),
7280
- %q{m { @1 + @15 }},
7281
- %q{^^^^^^^^^^^^^^ expression
7282
- | ^^ name (send/2.numparam/1)
7283
- | ^^ expression (send/2.numparam/1)
7284
- | ^^^ name (send/2.numparam/2)
7285
- | ^^^ expression (send/2.numparam/2)},
7253
+ s(:lvar, :_1), :+,
7254
+ s(:lvar, :_9))),
7255
+ %q{m { _1 + _9 }},
7256
+ %q{^^^^^^^^^^^^^ expression
7257
+ | ^^ name (send/2.lvar/1)
7258
+ | ^^ expression (send/2.lvar/1)
7259
+ | ^^ name (send/2.lvar/2)
7260
+ | ^^ expression (send/2.lvar/2)},
7286
7261
  SINCE_2_7)
7287
7262
 
7288
7263
  assert_parses(
7289
7264
  s(:numblock,
7290
7265
  s(:send, nil, :m),
7291
- 15,
7266
+ 9,
7292
7267
  s(:send,
7293
- s(:numparam, 1), :+,
7294
- s(:numparam, 15))),
7295
- %q{m do @1 + @15 end},
7296
- %q{^^^^^^^^^^^^^^^^^ expression
7297
- | ^^ name (send/2.numparam/1)
7298
- | ^^ expression (send/2.numparam/1)
7299
- | ^^^ name (send/2.numparam/2)
7300
- | ^^^ expression (send/2.numparam/2)},
7268
+ s(:lvar, :_1), :+,
7269
+ s(:lvar, :_9))),
7270
+ %q{m do _1 + _9 end},
7271
+ %q{^^^^^^^^^^^^^^^^ expression
7272
+ | ^^ name (send/2.lvar/1)
7273
+ | ^^ expression (send/2.lvar/1)
7274
+ | ^^ name (send/2.lvar/2)
7275
+ | ^^ expression (send/2.lvar/2)},
7301
7276
  SINCE_2_7)
7302
7277
 
7303
7278
  # Lambdas
@@ -7305,31 +7280,31 @@ class TestParser < Minitest::Test
7305
7280
  assert_parses(
7306
7281
  s(:numblock,
7307
7282
  s(:lambda),
7308
- 15,
7283
+ 9,
7309
7284
  s(:send,
7310
- s(:numparam, 1), :+,
7311
- s(:numparam, 15))),
7312
- %q{-> { @1 + @15}},
7313
- %q{^^^^^^^^^^^^^^ expression
7314
- | ^^ name (send.numparam/1)
7315
- | ^^ expression (send.numparam/1)
7316
- | ^^^ name (send.numparam/2)
7317
- | ^^^ expression (send.numparam/2)},
7285
+ s(:lvar, :_1), :+,
7286
+ s(:lvar, :_9))),
7287
+ %q{-> { _1 + _9}},
7288
+ %q{^^^^^^^^^^^^^ expression
7289
+ | ^^ name (send.lvar/1)
7290
+ | ^^ expression (send.lvar/1)
7291
+ | ^^ name (send.lvar/2)
7292
+ | ^^ expression (send.lvar/2)},
7318
7293
  SINCE_2_7)
7319
7294
 
7320
7295
  assert_parses(
7321
7296
  s(:numblock,
7322
7297
  s(:lambda),
7323
- 15,
7298
+ 9,
7324
7299
  s(:send,
7325
- s(:numparam, 1), :+,
7326
- s(:numparam, 15))),
7327
- %q{-> do @1 + @15 end},
7328
- %q{^^^^^^^^^^^^^^^^^^ expression
7329
- | ^^ name (send.numparam/1)
7330
- | ^^ expression (send.numparam/1)
7331
- | ^^^ name (send.numparam/2)
7332
- | ^^^ expression (send.numparam/2)},
7300
+ s(:lvar, :_1), :+,
7301
+ s(:lvar, :_9))),
7302
+ %q{-> do _1 + _9 end},
7303
+ %q{^^^^^^^^^^^^^^^^^ expression
7304
+ | ^^ name (send.lvar/1)
7305
+ | ^^ expression (send.lvar/1)
7306
+ | ^^ name (send.lvar/2)
7307
+ | ^^ expression (send.lvar/2)},
7333
7308
  SINCE_2_7)
7334
7309
  end
7335
7310
 
@@ -7338,37 +7313,37 @@ class TestParser < Minitest::Test
7338
7313
 
7339
7314
  assert_diagnoses(
7340
7315
  [:error, :ordinary_param_defined],
7341
- %q{m { || @1 } },
7316
+ %q{m { || _1 } },
7342
7317
  %q{ ^^ location},
7343
7318
  SINCE_2_7)
7344
7319
 
7345
7320
  assert_diagnoses(
7346
7321
  [:error, :ordinary_param_defined],
7347
- %q{m { |a| @1 } },
7322
+ %q{m { |a| _1 } },
7348
7323
  %q{ ^^ location},
7349
7324
  SINCE_2_7)
7350
7325
 
7351
7326
  assert_diagnoses(
7352
7327
  [:error, :ordinary_param_defined],
7353
- %q{m do || @1 end },
7328
+ %q{m do || _1 end },
7354
7329
  %q{ ^^ location},
7355
7330
  SINCE_2_7)
7356
7331
 
7357
7332
  assert_diagnoses(
7358
7333
  [:error, :ordinary_param_defined],
7359
- %q{m do |a, b| @1 end },
7334
+ %q{m do |a, b| _1 end },
7360
7335
  %q{ ^^ location},
7361
7336
  SINCE_2_7)
7362
7337
 
7363
7338
  assert_diagnoses(
7364
7339
  [:error, :ordinary_param_defined],
7365
- %q{m { |x = @1| }},
7340
+ %q{m { |x = _1| }},
7366
7341
  %q{ ^^ location},
7367
7342
  SINCE_2_7)
7368
7343
 
7369
7344
  assert_diagnoses(
7370
7345
  [:error, :ordinary_param_defined],
7371
- %q{m { |x: @1| }},
7346
+ %q{m { |x: _1| }},
7372
7347
  %q{ ^^ location},
7373
7348
  SINCE_2_7)
7374
7349
 
@@ -7376,77 +7351,161 @@ class TestParser < Minitest::Test
7376
7351
 
7377
7352
  assert_diagnoses(
7378
7353
  [:error, :ordinary_param_defined],
7379
- %q{->() { @1 } },
7354
+ %q{->() { _1 } },
7380
7355
  %q{ ^^ location},
7381
7356
  SINCE_2_7)
7382
7357
 
7383
7358
  assert_diagnoses(
7384
7359
  [:error, :ordinary_param_defined],
7385
- %q{->(a) { @1 } },
7360
+ %q{->(a) { _1 } },
7386
7361
  %q{ ^^ location},
7387
7362
  SINCE_2_7)
7388
7363
 
7389
7364
  assert_diagnoses(
7390
7365
  [:error, :ordinary_param_defined],
7391
- %q{->() do @1 end },
7366
+ %q{->() do _1 end },
7392
7367
  %q{ ^^ location},
7393
7368
  SINCE_2_7)
7394
7369
 
7395
7370
  assert_diagnoses(
7396
7371
  [:error, :ordinary_param_defined],
7397
- %q{->(a, b) do @1 end},
7372
+ %q{->(a, b) do _1 end},
7398
7373
  %q{ ^^ location},
7399
7374
  SINCE_2_7)
7400
7375
 
7401
7376
  assert_diagnoses(
7402
7377
  [:error, :ordinary_param_defined],
7403
- %q{->(x=@1) {}},
7378
+ %q{->(x=_1) {}},
7404
7379
  %q{ ^^ location},
7405
7380
  SINCE_2_7)
7406
7381
 
7407
7382
  assert_diagnoses(
7408
7383
  [:error, :ordinary_param_defined],
7409
- %q{->(x: @1) {}},
7384
+ %q{->(x: _1) {}},
7410
7385
  %q{ ^^ location},
7411
7386
  SINCE_2_7)
7412
7387
 
7413
7388
  assert_diagnoses(
7414
7389
  [:error, :ordinary_param_defined],
7415
- %q{proc {|;a| @1}},
7390
+ %q{proc {|;a| _1}},
7416
7391
  %q{ ^^ location},
7417
7392
  SINCE_2_7)
7418
7393
 
7419
7394
  assert_diagnoses(
7420
7395
  [:error, :ordinary_param_defined],
7421
- "proc {|\n| @1}",
7396
+ "proc {|\n| _1}",
7422
7397
  %q{ ^^ location},
7423
7398
  SINCE_2_7)
7424
7399
  end
7425
7400
 
7426
7401
  def test_numparam_outside_block
7402
+ assert_parses(
7403
+ s(:class,
7404
+ s(:const, nil, :A), nil,
7405
+ s(:send, nil, :_1)),
7406
+ %q{class A; _1; end},
7407
+ %q{},
7408
+ SINCE_2_7)
7409
+
7410
+ assert_parses(
7411
+ s(:module,
7412
+ s(:const, nil, :A),
7413
+ s(:send, nil, :_1)),
7414
+ %q{module A; _1; end},
7415
+ %q{},
7416
+ SINCE_2_7)
7417
+
7418
+ assert_parses(
7419
+ s(:sclass,
7420
+ s(:lvar, :foo),
7421
+ s(:send, nil, :_1)),
7422
+ %q{class << foo; _1; end},
7423
+ %q{},
7424
+ SINCE_2_7)
7425
+
7426
+ assert_parses(
7427
+ s(:defs,
7428
+ s(:self), :m,
7429
+ s(:args),
7430
+ s(:send, nil, :_1)),
7431
+ %q{def self.m; _1; end},
7432
+ %q{},
7433
+ SINCE_2_7)
7434
+
7435
+ assert_parses(
7436
+ s(:send, nil, :_1),
7437
+ %q{_1},
7438
+ %q{},
7439
+ SINCE_2_7)
7440
+ end
7441
+
7442
+ def test_assignment_to_numparams
7443
+ assert_parses(
7444
+ s(:block,
7445
+ s(:send, nil, :proc),
7446
+ s(:args),
7447
+ s(:lvasgn, :_1,
7448
+ s(:nil))),
7449
+ %q{proc {_1 = nil}},
7450
+ %q{},
7451
+ SINCE_2_7)
7452
+
7427
7453
  assert_diagnoses(
7428
- [:error, :numparam_outside_block],
7429
- %q{class A; @1; end},
7430
- %q{ ^^ location},
7454
+ [:error, :cant_assign_to_numparam, { :name => '_1' }],
7455
+ %q{proc {_1; _1 = nil}},
7456
+ %q{ ^^ location},
7431
7457
  SINCE_2_7)
7432
7458
 
7433
7459
  assert_diagnoses(
7434
- [:error, :numparam_outside_block],
7435
- %q{module A; @1; end},
7460
+ [:error, :cant_assign_to_numparam, { :name => '_1' }],
7461
+ %q{proc {_1; _1, foo = [nil, nil]}},
7436
7462
  %q{ ^^ location},
7437
7463
  SINCE_2_7)
7438
7464
 
7439
7465
  assert_diagnoses(
7440
- [:error, :numparam_outside_block],
7441
- %q{class << foo; @1; end},
7442
- %q{ ^^ location},
7466
+ [:error, :cant_assign_to_numparam, { :name => '_1' }],
7467
+ %q{proc {_9; _1 = nil}},
7468
+ %q{ ^^ location},
7443
7469
  SINCE_2_7)
7444
7470
 
7445
7471
  assert_diagnoses(
7446
- [:error, :numparam_outside_block],
7447
- %q{def self.m; @1; end},
7448
- %q{ ^^ location},
7472
+ [:error, :cant_assign_to_numparam, { :name => '_9' }],
7473
+ %q{proc {_1; _9 = nil}},
7474
+ %q{ ^^ location},
7475
+ SINCE_2_7)
7476
+
7477
+ refute_diagnoses(
7478
+ %q{proc { _1 = nil; _1}},
7479
+ SINCE_2_7)
7480
+ end
7481
+
7482
+ def test_numparams_in_nested_blocks
7483
+ assert_diagnoses(
7484
+ [:error, :numparam_used_in_outer_scope],
7485
+ %q{foo { _1; bar { _2 }; }},
7486
+ %q{ ^^ location},
7487
+ SINCE_2_7)
7488
+
7489
+ assert_diagnoses(
7490
+ [:error, :numparam_used_in_outer_scope],
7491
+ %q{-> { _1; -> { _2 }; }},
7492
+ %q{ ^^ location},
7449
7493
  SINCE_2_7)
7494
+
7495
+ [
7496
+ ['class A', 'end'],
7497
+ ['class << foo', 'end'],
7498
+ ['def m', 'end'],
7499
+ ['def self.m', 'end']
7500
+ ].each do |open_scope, close_scope|
7501
+ refute_diagnoses(
7502
+ "proc { _1; #{open_scope}; proc { _2 }; #{close_scope}; }",
7503
+ SINCE_2_7)
7504
+
7505
+ refute_diagnoses(
7506
+ "-> { _1; #{open_scope}; -> { _2 }; #{close_scope}; }",
7507
+ SINCE_2_7)
7508
+ end
7450
7509
  end
7451
7510
 
7452
7511
  def test_ruby_bug_15789
@@ -7458,9 +7517,9 @@ class TestParser < Minitest::Test
7458
7517
  s(:optarg, :a,
7459
7518
  s(:numblock,
7460
7519
  s(:lambda), 1,
7461
- s(:numparam, 1)))),
7520
+ s(:lvar, :_1)))),
7462
7521
  s(:lvar, :a))),
7463
- %q{m ->(a = ->{@1}) {a}},
7522
+ %q{m ->(a = ->{_1}) {a}},
7464
7523
  %q{},
7465
7524
  SINCE_2_7)
7466
7525
 
@@ -7472,9 +7531,9 @@ class TestParser < Minitest::Test
7472
7531
  s(:kwoptarg, :a,
7473
7532
  s(:numblock,
7474
7533
  s(:lambda), 1,
7475
- s(:numparam, 1)))),
7534
+ s(:lvar, :_1)))),
7476
7535
  s(:lvar, :a))),
7477
- %q{m ->(a: ->{@1}) {a}},
7536
+ %q{m ->(a: ->{_1}) {a}},
7478
7537
  %q{},
7479
7538
  SINCE_2_7)
7480
7539
  end
@@ -7576,4 +7635,1709 @@ class TestParser < Minitest::Test
7576
7635
  %q{},
7577
7636
  ALL_VERSIONS)
7578
7637
  end
7638
+
7639
+ def test_comments_before_leading_dot__27
7640
+ assert_parses(
7641
+ s(:send,
7642
+ s(:send, nil, :a), :foo),
7643
+ %Q{a #\n#\n.foo\n},
7644
+ %q{},
7645
+ SINCE_2_7)
7646
+
7647
+ assert_parses(
7648
+ s(:csend,
7649
+ s(:send, nil, :a), :foo),
7650
+ %Q{a #\n#\n&.foo\n},
7651
+ %q{},
7652
+ SINCE_2_7)
7653
+ end
7654
+
7655
+ def test_comments_before_leading_dot__before_27
7656
+ assert_diagnoses(
7657
+ [:error, :unexpected_token, { :token => 'tDOT' }],
7658
+ %q{a #!#!.foo!}.gsub('!', "\n"),
7659
+ %q{ ^ location},
7660
+ ALL_VERSIONS - SINCE_2_7)
7661
+
7662
+ assert_diagnoses(
7663
+ [:error, :unexpected_token, { :token => 'tAMPER' }],
7664
+ %q{a #!#!&.foo!}.gsub('!', "\n"),
7665
+ %q{ ^ location},
7666
+ ALL_VERSIONS - SINCE_2_7)
7667
+
7668
+ assert_diagnoses(
7669
+ [:error, :unexpected_token, { :token => 'tDOT' }],
7670
+ %q{a #!#!.:foo!}.gsub('!', "\n"),
7671
+ %q{ ^ location},
7672
+ ALL_VERSIONS - SINCE_2_7)
7673
+ end
7674
+
7675
+ def test_circular_argument_reference_error
7676
+ assert_diagnoses(
7677
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7678
+ %q{def m(foo = foo) end},
7679
+ %q{ ^^^ location},
7680
+ SINCE_2_7)
7681
+
7682
+ assert_diagnoses(
7683
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7684
+ %q{def m(foo: foo) end},
7685
+ %q{ ^^^ location},
7686
+ SINCE_2_7)
7687
+
7688
+ assert_diagnoses(
7689
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7690
+ %q{m { |foo = foo| } },
7691
+ %q{ ^^^ location},
7692
+ SINCE_2_7)
7693
+
7694
+ assert_diagnoses(
7695
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7696
+ %q{m { |foo: foo| } },
7697
+ %q{ ^^^ location},
7698
+ SINCE_2_7)
7699
+
7700
+ # Traversing
7701
+
7702
+ assert_diagnoses(
7703
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7704
+ %q{def m(foo = class << foo; end) end},
7705
+ %q{ ^^^ location},
7706
+ SINCE_2_7)
7707
+
7708
+ assert_diagnoses(
7709
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7710
+ %q{def m(foo = def foo.m; end); end},
7711
+ %q{ ^^^ location},
7712
+ SINCE_2_7)
7713
+
7714
+ assert_diagnoses(
7715
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7716
+ %q{m { |foo = proc { 1 + foo }| } },
7717
+ %q{ ^^^ location},
7718
+ SINCE_2_7)
7719
+
7720
+ # Valid cases
7721
+
7722
+ [
7723
+ 'm { |foo = class A; foo; end| }',
7724
+ 'm { |foo = class << self; foo; end| }',
7725
+ 'm { |foo = def m(foo = bar); foo; end| }',
7726
+ 'm { |foo = def m(bar = foo); foo; end| }',
7727
+ 'm { |foo = def self.m(bar = foo); foo; end| }',
7728
+ 'def m(foo = def m; foo; end) end',
7729
+ 'def m(foo = def self.m; foo; end) end',
7730
+ 'm { |foo = proc { |bar| 1 + foo }| }',
7731
+ 'm { |foo = proc { || 1 + foo }| }'
7732
+ ].each do |code|
7733
+ refute_diagnoses(code, SINCE_2_7)
7734
+ end
7735
+ end
7736
+
7737
+ def test_forward_args
7738
+ assert_parses(
7739
+ s(:def, :foo,
7740
+ s(:forward_args),
7741
+ s(:send, nil, :bar,
7742
+ s(:forwarded_args))),
7743
+ %q{def foo(...); bar(...); end},
7744
+ %q{ ~ begin (forward_args)
7745
+ | ~~~~~ expression (forward_args)
7746
+ | ~ end (forward_args)
7747
+ | ~~~ expression (send.forwarded_args)},
7748
+ SINCE_2_7)
7749
+
7750
+ assert_parses(
7751
+ s(:def, :foo,
7752
+ s(:forward_args),
7753
+ s(:super,
7754
+ s(:forwarded_args))),
7755
+ %q{def foo(...); super(...); end},
7756
+ %q{ ~ begin (forward_args)
7757
+ | ~~~~~ expression (forward_args)
7758
+ | ~ end (forward_args)
7759
+ | ~~~ expression (super.forwarded_args)},
7760
+ SINCE_2_7)
7761
+
7762
+ assert_parses(
7763
+ s(:def, :foo,
7764
+ s(:forward_args),
7765
+ nil),
7766
+ %q{def foo(...); end},
7767
+ %q{},
7768
+ SINCE_2_7)
7769
+
7770
+ assert_diagnoses(
7771
+ [:error, :block_and_blockarg],
7772
+ %q{def foo(...) bar(...) { }; end},
7773
+ %q{ ^^^ location
7774
+ | ~ highlights (0)},
7775
+ SINCE_2_7)
7776
+
7777
+ assert_diagnoses(
7778
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7779
+ %q{foo do |...| end},
7780
+ %q{ ^^^ location},
7781
+ SINCE_2_7)
7782
+
7783
+ assert_diagnoses(
7784
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7785
+ %q{foo { |...| }},
7786
+ %q{ ^^^ location},
7787
+ SINCE_2_7)
7788
+
7789
+ assert_diagnoses(
7790
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7791
+ %q{def foo(x,y,z); bar(...); end},
7792
+ %q{ ^^^ location},
7793
+ SINCE_2_7)
7794
+
7795
+ assert_diagnoses(
7796
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7797
+ %q{def foo(x,y,z); super(...); end},
7798
+ %q{ ^^^ location},
7799
+ SINCE_2_7)
7800
+
7801
+ assert_diagnoses(
7802
+ [:error, :unexpected_token, { :token => 'tDOT3' }],
7803
+ %q{->... {}},
7804
+ %q{ ^^^ location},
7805
+ SINCE_2_7)
7806
+
7807
+ assert_diagnoses(
7808
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7809
+ %q{->(...) {}},
7810
+ %q{ ^^^ location},
7811
+ SINCE_2_7)
7812
+
7813
+ # Here and below the parser asssumes that
7814
+ # it can be a beginningless range, so the error comes after reducing right paren
7815
+ assert_diagnoses(
7816
+ [:error, :unexpected_token, { :token => 'tRPAREN' }],
7817
+ %q{def foo(...); yield(...); end},
7818
+ %q{ ^ location},
7819
+ SINCE_2_7)
7820
+
7821
+ assert_diagnoses(
7822
+ [:error, :unexpected_token, { :token => 'tRPAREN' }],
7823
+ %q{def foo(...); return(...); end},
7824
+ %q{ ^ location},
7825
+ SINCE_2_7)
7826
+
7827
+ assert_diagnoses(
7828
+ [:error, :unexpected_token, { :token => 'tRPAREN' }],
7829
+ %q{def foo(...); a = (...); end},
7830
+ %q{ ^ location},
7831
+ SINCE_2_7)
7832
+
7833
+ assert_diagnoses(
7834
+ [:error, :unexpected_token, { :token => 'tRBRACK' }],
7835
+ %q{def foo(...); [...]; end},
7836
+ %q{ ^ location},
7837
+ SINCE_2_7)
7838
+
7839
+ assert_diagnoses(
7840
+ [:error, :unexpected_token, { :token => 'tRBRACK' }],
7841
+ %q{def foo(...) bar[...]; end},
7842
+ %q{ ^ location},
7843
+ SINCE_2_7)
7844
+
7845
+ assert_diagnoses(
7846
+ [:error, :unexpected_token, { :token => 'tRBRACK' }],
7847
+ %q{def foo(...) bar[...] = x; end},
7848
+ %q{ ^ location},
7849
+ SINCE_2_7)
7850
+
7851
+ assert_diagnoses(
7852
+ [:error, :unexpected_token, { :token => 'tRPAREN' }],
7853
+ %q{def foo(...) defined?(...); end},
7854
+ %q{ ^ location},
7855
+ SINCE_2_7)
7856
+
7857
+ assert_diagnoses(
7858
+ [:error, :unexpected_token, { :token => 'tDOT3' }],
7859
+ %q{def foo ...; end},
7860
+ %q{ ^^^ location},
7861
+ SINCE_2_7)
7862
+ end
7863
+
7864
+ def test_erange_without_parentheses_at_eol
7865
+ assert_diagnoses(
7866
+ [:warning, :triple_dot_at_eol],
7867
+ %Q{1...\n2},
7868
+ %q{ ^^^ location},
7869
+ SINCE_2_7)
7870
+
7871
+ refute_diagnoses('(1...)', SINCE_2_7)
7872
+ refute_diagnoses("(1...\n)", SINCE_2_7)
7873
+ refute_diagnoses("[1...\n]", SINCE_2_7)
7874
+ refute_diagnoses("{a: 1...\n2}", SINCE_2_7)
7875
+ end
7876
+
7877
+ def test_embedded_document_with_eof
7878
+ refute_diagnoses("=begin\n""=end", SINCE_2_7)
7879
+ refute_diagnoses("=begin\n""=end\0", SINCE_2_7)
7880
+ refute_diagnoses("=begin\n""=end\C-d", SINCE_2_7)
7881
+ refute_diagnoses("=begin\n""=end\C-z", SINCE_2_7)
7882
+
7883
+ assert_diagnoses(
7884
+ [:fatal, :embedded_document],
7885
+ "=begin\n",
7886
+ %q{},
7887
+ SINCE_2_7)
7888
+
7889
+ assert_diagnoses(
7890
+ [:fatal, :embedded_document],
7891
+ "=begin",
7892
+ %q{},
7893
+ SINCE_2_7)
7894
+ end
7895
+
7896
+ def test_interp_digit_var
7897
+ # '#@1'
7898
+ assert_parses(
7899
+ s(:str, '#@1'),
7900
+ %q{ '#@1' },
7901
+ %q{},
7902
+ ALL_VERSIONS)
7903
+
7904
+ assert_parses(
7905
+ s(:str, '#@@1'),
7906
+ %q{ '#@@1' },
7907
+ %q{},
7908
+ ALL_VERSIONS)
7909
+
7910
+ # <<-'HERE'
7911
+ # #@1
7912
+ # HERE
7913
+ assert_parses(
7914
+ s(:str, '#@1' + "\n"),
7915
+ %q{<<-'HERE'!#@1!HERE}.gsub('!', "\n"),
7916
+ %q{},
7917
+ ALL_VERSIONS)
7918
+
7919
+ assert_parses(
7920
+ s(:str, '#@@1' + "\n"),
7921
+ %q{<<-'HERE'!#@@1!HERE}.gsub('!', "\n"),
7922
+ %q{},
7923
+ ALL_VERSIONS)
7924
+
7925
+ # %q{#@1}
7926
+ assert_parses(
7927
+ s(:str, '#@1'),
7928
+ %q{ %q{#@1} },
7929
+ %q{},
7930
+ ALL_VERSIONS)
7931
+
7932
+ assert_parses(
7933
+ s(:str, '#@@1'),
7934
+ %q{ %q{#@@1} },
7935
+ %q{},
7936
+ ALL_VERSIONS)
7937
+
7938
+ # "#@1"
7939
+ assert_diagnoses(
7940
+ [:error, :ivar_name, { :name => '@1' }],
7941
+ %q{ "#@1" },
7942
+ %q{ ^^ location},
7943
+ ALL_VERSIONS - SINCE_2_7)
7944
+
7945
+ assert_diagnoses(
7946
+ [:error, :cvar_name, { :name => '@@1' }],
7947
+ %q{ "#@@1" },
7948
+ %q{ ^^^ location},
7949
+ ALL_VERSIONS - SINCE_2_7)
7950
+
7951
+ assert_parses(
7952
+ s(:str, '#@1'),
7953
+ %q{ "#@1" },
7954
+ %q{},
7955
+ SINCE_2_7)
7956
+
7957
+ assert_parses(
7958
+ s(:str, '#@@1'),
7959
+ %q{ "#@@1" },
7960
+ %q{},
7961
+ SINCE_2_7)
7962
+
7963
+ # <<-"HERE"
7964
+ # #@1
7965
+ # HERE
7966
+ assert_diagnoses(
7967
+ [:error, :ivar_name, { :name => '@1' }],
7968
+ %q{ <<-"HERE"!#@1!HERE }.gsub('!', "\n"),
7969
+ %q{ ^^ location},
7970
+ ALL_VERSIONS - SINCE_2_7)
7971
+
7972
+ assert_diagnoses(
7973
+ [:error, :cvar_name, { :name => '@@1' }],
7974
+ %q{ <<-"HERE"!#@@1!HERE }.gsub('!', "\n"),
7975
+ %q{ ^^^ location},
7976
+ ALL_VERSIONS - SINCE_2_7)
7977
+
7978
+ assert_parses(
7979
+ s(:str, '#@1' + "\n"),
7980
+ %q{<<-"HERE"!#@1!HERE}.gsub('!', "\n"),
7981
+ %q{},
7982
+ SINCE_2_7)
7983
+
7984
+ assert_parses(
7985
+ s(:str, '#@@1' + "\n"),
7986
+ %q{<<-"HERE"!#@@1!HERE}.gsub('!', "\n"),
7987
+ %q{},
7988
+ SINCE_2_7)
7989
+
7990
+ # %{#@1}
7991
+ assert_diagnoses(
7992
+ [:error, :ivar_name, { :name => '@1' }],
7993
+ %q{ %{#@1} },
7994
+ %q{ ^^ location},
7995
+ ALL_VERSIONS - SINCE_2_7)
7996
+
7997
+ assert_diagnoses(
7998
+ [:error, :cvar_name, { :name => '@@1' }],
7999
+ %q{ %{#@@1} },
8000
+ %q{ ^^^ location},
8001
+ ALL_VERSIONS - SINCE_2_7)
8002
+
8003
+ assert_parses(
8004
+ s(:str, '#@1'),
8005
+ %q{ %{#@1} },
8006
+ %q{},
8007
+ SINCE_2_7)
8008
+
8009
+ assert_parses(
8010
+ s(:str, '#@@1'),
8011
+ %q{ %{#@@1} },
8012
+ %q{},
8013
+ SINCE_2_7)
8014
+
8015
+ # %Q{#@1}
8016
+ assert_diagnoses(
8017
+ [:error, :ivar_name, { :name => '@1' }],
8018
+ %q{ %Q{#@1} },
8019
+ %q{ ^^ location},
8020
+ ALL_VERSIONS - SINCE_2_7)
8021
+
8022
+ assert_diagnoses(
8023
+ [:error, :cvar_name, { :name => '@@1' }],
8024
+ %q{ %Q{#@@1} },
8025
+ %q{ ^^^ location},
8026
+ ALL_VERSIONS - SINCE_2_7)
8027
+
8028
+ assert_parses(
8029
+ s(:str, '#@1'),
8030
+ %q{ %Q{#@1} },
8031
+ %q{},
8032
+ SINCE_2_7)
8033
+
8034
+ assert_parses(
8035
+ s(:str, '#@@1'),
8036
+ %q{ %Q{#@@1} },
8037
+ %q{},
8038
+ SINCE_2_7)
8039
+
8040
+ # %w[#@1]
8041
+ assert_parses(
8042
+ s(:array,
8043
+ s(:str, '#@1')),
8044
+ %q{ %w[ #@1 ] },
8045
+ %q{},
8046
+ ALL_VERSIONS)
8047
+
8048
+ assert_parses(
8049
+ s(:array,
8050
+ s(:str, '#@@1')),
8051
+ %q{ %w[ #@@1 ] },
8052
+ %q{},
8053
+ ALL_VERSIONS)
8054
+
8055
+ # %W[#@1]
8056
+ assert_diagnoses(
8057
+ [:error, :ivar_name, { :name => '@1' }],
8058
+ %q{ %W[#@1] },
8059
+ %q{ ^^ location},
8060
+ ALL_VERSIONS - SINCE_2_7)
8061
+
8062
+ assert_diagnoses(
8063
+ [:error, :cvar_name, { :name => '@@1' }],
8064
+ %q{ %W[#@@1] },
8065
+ %q{ ^^^ location},
8066
+ ALL_VERSIONS - SINCE_2_7)
8067
+
8068
+ assert_parses(
8069
+ s(:array,
8070
+ s(:str, '#@1')),
8071
+ %q{ %W[#@1] },
8072
+ %q{},
8073
+ SINCE_2_7)
8074
+
8075
+ assert_parses(
8076
+ s(:array,
8077
+ s(:str, '#@@1')),
8078
+ %q{ %W[#@@1] },
8079
+ %q{},
8080
+ SINCE_2_7)
8081
+
8082
+ # %i[#@1]
8083
+ assert_parses(
8084
+ s(:array,
8085
+ s(:sym, :'#@1')),
8086
+ %q{ %i[ #@1 ] },
8087
+ %q{},
8088
+ SINCE_2_0)
8089
+
8090
+ assert_parses(
8091
+ s(:array,
8092
+ s(:sym, :'#@@1')),
8093
+ %q{ %i[ #@@1 ] },
8094
+ %q{},
8095
+ SINCE_2_0)
8096
+
8097
+ # %I[#@1]
8098
+ assert_diagnoses(
8099
+ [:error, :ivar_name, { :name => '@1' }],
8100
+ %q{ %I[#@1] },
8101
+ %q{ ^^ location},
8102
+ SINCE_2_0 - SINCE_2_7)
8103
+
8104
+ assert_diagnoses(
8105
+ [:error, :cvar_name, { :name => '@@1' }],
8106
+ %q{ %I[#@@1] },
8107
+ %q{ ^^^ location},
8108
+ SINCE_2_0 - SINCE_2_7)
8109
+
8110
+ assert_parses(
8111
+ s(:array,
8112
+ s(:sym, :'#@1')),
8113
+ %q{ %I[#@1] },
8114
+ %q{},
8115
+ SINCE_2_7)
8116
+
8117
+ assert_parses(
8118
+ s(:array,
8119
+ s(:sym, :'#@@1')),
8120
+ %q{ %I[#@@1] },
8121
+ %q{},
8122
+ SINCE_2_7)
8123
+
8124
+ # :'#@1'
8125
+ assert_parses(
8126
+ s(:sym, :'#@1'),
8127
+ %q{ :'#@1' },
8128
+ %q{},
8129
+ ALL_VERSIONS)
8130
+
8131
+ assert_parses(
8132
+ s(:sym, :'#@@1'),
8133
+ %q{ :'#@@1' },
8134
+ %q{},
8135
+ ALL_VERSIONS)
8136
+
8137
+ # %s{#@1}
8138
+ assert_parses(
8139
+ s(:sym, :'#@1'),
8140
+ %q{ %s{#@1} },
8141
+ %q{},
8142
+ ALL_VERSIONS)
8143
+
8144
+ assert_parses(
8145
+ s(:sym, :'#@@1'),
8146
+ %q{ %s{#@@1} },
8147
+ %q{},
8148
+ ALL_VERSIONS)
8149
+
8150
+ # :"#@1"
8151
+ assert_diagnoses(
8152
+ [:error, :ivar_name, { :name => '@1' }],
8153
+ %q{ :"#@1" },
8154
+ %q{ ^^ location},
8155
+ ALL_VERSIONS - SINCE_2_7)
8156
+
8157
+ assert_diagnoses(
8158
+ [:error, :cvar_name, { :name => '@@1' }],
8159
+ %q{ :"#@@1" },
8160
+ %q{ ^^^ location},
8161
+ ALL_VERSIONS - SINCE_2_7)
8162
+
8163
+ assert_parses(
8164
+ s(:sym, :'#@1'),
8165
+ %q{ :"#@1" },
8166
+ %q{},
8167
+ SINCE_2_7)
8168
+
8169
+ assert_parses(
8170
+ s(:sym, :'#@@1'),
8171
+ %q{ :"#@@1" },
8172
+ %q{},
8173
+ SINCE_2_7)
8174
+
8175
+ # /#@1/
8176
+ assert_diagnoses(
8177
+ [:error, :ivar_name, { :name => '@1' }],
8178
+ %q{ /#@1/ },
8179
+ %q{ ^^ location},
8180
+ ALL_VERSIONS - SINCE_2_7)
8181
+
8182
+ assert_diagnoses(
8183
+ [:error, :cvar_name, { :name => '@@1' }],
8184
+ %q{ /#@@1/ },
8185
+ %q{ ^^^ location},
8186
+ ALL_VERSIONS - SINCE_2_7)
8187
+
8188
+ assert_parses(
8189
+ s(:regexp,
8190
+ s(:str, '#@1'),
8191
+ s(:regopt)),
8192
+ %q{ /#@1/ },
8193
+ %q{},
8194
+ SINCE_2_7)
8195
+
8196
+ assert_parses(
8197
+ s(:regexp,
8198
+ s(:str, '#@@1'),
8199
+ s(:regopt)),
8200
+ %q{ /#@@1/ },
8201
+ %q{},
8202
+ SINCE_2_7)
8203
+
8204
+ # %r{#@1}
8205
+ assert_diagnoses(
8206
+ [:error, :ivar_name, { :name => '@1' }],
8207
+ %q{ %r{#@1} },
8208
+ %q{ ^^ location},
8209
+ ALL_VERSIONS - SINCE_2_7)
8210
+
8211
+ assert_diagnoses(
8212
+ [:error, :cvar_name, { :name => '@@1' }],
8213
+ %q{ %r{#@@1} },
8214
+ %q{ ^^^ location},
8215
+ ALL_VERSIONS - SINCE_2_7)
8216
+
8217
+ assert_parses(
8218
+ s(:regexp,
8219
+ s(:str, '#@1'),
8220
+ s(:regopt)),
8221
+ %q{ %r{#@1} },
8222
+ %q{},
8223
+ SINCE_2_7)
8224
+
8225
+ assert_parses(
8226
+ s(:regexp,
8227
+ s(:str, '#@@1'),
8228
+ s(:regopt)),
8229
+ %q{ %r{#@@1} },
8230
+ %q{},
8231
+ SINCE_2_7)
8232
+
8233
+ # %x{#@1}
8234
+ assert_diagnoses(
8235
+ [:error, :ivar_name, { :name => '@1' }],
8236
+ %q{ %x{#@1} },
8237
+ %q{ ^^ location},
8238
+ ALL_VERSIONS - SINCE_2_7)
8239
+
8240
+ assert_diagnoses(
8241
+ [:error, :cvar_name, { :name => '@@1' }],
8242
+ %q{ %x{#@@1} },
8243
+ %q{ ^^^ location},
8244
+ ALL_VERSIONS - SINCE_2_7)
8245
+
8246
+ assert_parses(
8247
+ s(:xstr,
8248
+ s(:str, '#@1')),
8249
+ %q{ %x{#@1} },
8250
+ %q{},
8251
+ SINCE_2_7)
8252
+
8253
+ assert_parses(
8254
+ s(:xstr,
8255
+ s(:str, '#@@1')),
8256
+ %q{ %x{#@@1} },
8257
+ %q{},
8258
+ SINCE_2_7)
8259
+
8260
+ # `#@1`
8261
+ assert_diagnoses(
8262
+ [:error, :ivar_name, { :name => '@1' }],
8263
+ %q{ `#@1` },
8264
+ %q{ ^^ location},
8265
+ ALL_VERSIONS - SINCE_2_7)
8266
+
8267
+ assert_diagnoses(
8268
+ [:error, :cvar_name, { :name => '@@1' }],
8269
+ %q{ `#@@1` },
8270
+ %q{ ^^^ location},
8271
+ ALL_VERSIONS - SINCE_2_7)
8272
+
8273
+ assert_parses(
8274
+ s(:xstr,
8275
+ s(:str, '#@1')),
8276
+ %q{ `#@1` },
8277
+ %q{},
8278
+ SINCE_2_7)
8279
+
8280
+ assert_parses(
8281
+ s(:xstr,
8282
+ s(:str, '#@@1')),
8283
+ %q{ `#@@1` },
8284
+ %q{},
8285
+ SINCE_2_7)
8286
+
8287
+ # <<-`HERE`
8288
+ # #@1
8289
+ # HERE
8290
+ assert_diagnoses(
8291
+ [:error, :ivar_name, { :name => '@1' }],
8292
+ %q{ <<-`HERE`!#@1!HERE }.gsub('!', "\n"),
8293
+ %q{ ^^ location},
8294
+ ALL_VERSIONS - SINCE_2_7)
8295
+
8296
+ assert_diagnoses(
8297
+ [:error, :cvar_name, { :name => '@@1' }],
8298
+ %q{ <<-`HERE`!#@@1!HERE }.gsub('!', "\n"),
8299
+ %q{ ^^^ location},
8300
+ ALL_VERSIONS - SINCE_2_7)
8301
+
8302
+ assert_parses(
8303
+ s(:xstr,
8304
+ s(:str, '#@1' + "\n")),
8305
+ %q{<<-`HERE`!#@1!HERE}.gsub('!', "\n"),
8306
+ %q{},
8307
+ SINCE_2_7)
8308
+
8309
+ assert_parses(
8310
+ s(:xstr,
8311
+ s(:str, '#@@1' + "\n")),
8312
+ %q{<<-`HERE`!#@@1!HERE}.gsub('!', "\n"),
8313
+ %q{},
8314
+ SINCE_2_7)
8315
+ end
8316
+
8317
+ def assert_parses_pattern_match(ast, code, source_maps = '', versions = SINCE_2_7)
8318
+ case_pre = "case foo; "
8319
+ source_maps_offset = case_pre.length
8320
+ source_maps_prefix = ' ' * source_maps_offset
8321
+ source_maps = source_maps
8322
+ .lines
8323
+ .map { |line| source_maps_prefix + line.sub(/^\s*\|/, '') }
8324
+ .join("\n")
8325
+
8326
+ assert_parses(
8327
+ s(:case_match,
8328
+ s(:lvar, :foo),
8329
+ ast,
8330
+ nil),
8331
+ "#{case_pre}#{code}; end",
8332
+ source_maps,
8333
+ SINCE_2_7
8334
+ )
8335
+ end
8336
+
8337
+ def test_pattern_matching_single_match
8338
+ assert_parses_pattern_match(
8339
+ s(:in_pattern,
8340
+ s(:match_var, :x),
8341
+ nil,
8342
+ s(:lvar, :x)),
8343
+ %q{in x then x},
8344
+ %q{~~ keyword (in_pattern)
8345
+ |~~~~~~~~~~~ expression (in_pattern)
8346
+ | ~~~~ begin (in_pattern)
8347
+ | ~ expression (in_pattern.match_var)
8348
+ | ~ name (in_pattern.match_var)}
8349
+ )
8350
+ end
8351
+
8352
+ def test_pattern_matching_no_body
8353
+ assert_parses_pattern_match(
8354
+ s(:in_pattern,
8355
+ s(:int, 1), nil, nil),
8356
+ %q{in 1}
8357
+ )
8358
+ end
8359
+
8360
+ def test_pattern_matching_if_unless_modifiers
8361
+ assert_parses_pattern_match(
8362
+ s(:in_pattern,
8363
+ s(:match_var, :x),
8364
+ s(:if_guard, s(:true)),
8365
+ s(:nil)
8366
+ ),
8367
+ %q{in x if true; nil},
8368
+ %q{~~ keyword (in_pattern)
8369
+ |~~~~~~~~~~~~~~~~~ expression (in_pattern)
8370
+ | ~ begin (in_pattern)
8371
+ | ~~ keyword (in_pattern.if_guard)
8372
+ | ~~~~~~~ expression (in_pattern.if_guard)}
8373
+ )
8374
+
8375
+ assert_parses_pattern_match(
8376
+ s(:in_pattern,
8377
+ s(:match_var, :x),
8378
+ s(:unless_guard, s(:true)),
8379
+ s(:nil)
8380
+ ),
8381
+ %q{in x unless true; nil},
8382
+ %q{~~ keyword (in_pattern)
8383
+ |~~~~~~~~~~~~~~~~~~~~~ expression (in_pattern)
8384
+ | ~ begin (in_pattern)
8385
+ | ~~~~~~ keyword (in_pattern.unless_guard)
8386
+ | ~~~~~~~~~~~ expression (in_pattern.unless_guard)}
8387
+ )
8388
+ end
8389
+
8390
+ def test_pattern_matching_pin_variable
8391
+ assert_parses_pattern_match(
8392
+ s(:in_pattern,
8393
+ s(:pin, s(:lvar, :foo)),
8394
+ nil,
8395
+ s(:nil)),
8396
+ %q{in ^foo then nil},
8397
+ %q{ ~ selector (in_pattern.pin)
8398
+ | ~~~~ expression (in_pattern.pin)
8399
+ | ~~~ name (in_pattern.pin.lvar)}
8400
+ )
8401
+ end
8402
+
8403
+ def test_pattern_matching_implicit_array_match
8404
+ assert_parses_pattern_match(
8405
+ s(:in_pattern,
8406
+ s(:array_pattern_with_tail,
8407
+ s(:match_var, :x)),
8408
+ nil,
8409
+ s(:nil)),
8410
+ %q{in x, then nil},
8411
+ %q{ ~ expression (in_pattern.array_pattern_with_tail)}
8412
+ )
8413
+
8414
+ assert_parses_pattern_match(
8415
+ s(:in_pattern,
8416
+ s(:array_pattern,
8417
+ s(:match_rest,
8418
+ s(:match_var, :x))),
8419
+ nil,
8420
+ s(:nil)),
8421
+ %q{in *x then nil},
8422
+ %q{ ~~ expression (in_pattern.array_pattern)
8423
+ | ~ operator (in_pattern.array_pattern.match_rest)
8424
+ | ~ name (in_pattern.array_pattern.match_rest.match_var)}
8425
+ )
8426
+
8427
+ assert_parses_pattern_match(
8428
+ s(:in_pattern,
8429
+ s(:array_pattern,
8430
+ s(:match_rest)),
8431
+ nil,
8432
+ s(:nil)),
8433
+ %q{in * then nil},
8434
+ %q{ ~ expression (in_pattern.array_pattern)
8435
+ | ~ operator (in_pattern.array_pattern.match_rest)}
8436
+ )
8437
+
8438
+ assert_parses_pattern_match(
8439
+ s(:in_pattern,
8440
+ s(:array_pattern,
8441
+ s(:match_var, :x),
8442
+ s(:match_var, :y)),
8443
+ nil,
8444
+ s(:nil)),
8445
+ %q{in x, y then nil},
8446
+ %q{ ~~~~ expression (in_pattern.array_pattern)}
8447
+ )
8448
+
8449
+ assert_parses_pattern_match(
8450
+ s(:in_pattern,
8451
+ s(:array_pattern_with_tail,
8452
+ s(:match_var, :x),
8453
+ s(:match_var, :y)),
8454
+ nil,
8455
+ s(:nil)),
8456
+ %q{in x, y, then nil},
8457
+ %q{ ~~~~ expression (in_pattern.array_pattern_with_tail)}
8458
+ )
8459
+
8460
+ assert_parses_pattern_match(
8461
+ s(:in_pattern,
8462
+ s(:array_pattern,
8463
+ s(:match_var, :x),
8464
+ s(:match_rest, s(:match_var, :y)),
8465
+ s(:match_var, :z)),
8466
+ nil,
8467
+ s(:nil)),
8468
+ %q{in x, *y, z then nil},
8469
+ %q{ ~~~~~~~~ expression (in_pattern.array_pattern)}
8470
+ )
8471
+
8472
+ assert_parses_pattern_match(
8473
+ s(:in_pattern,
8474
+ s(:array_pattern,
8475
+ s(:match_rest, s(:match_var, :x)),
8476
+ s(:match_var, :y),
8477
+ s(:match_var, :z)),
8478
+ nil,
8479
+ s(:nil)),
8480
+ %q{in *x, y, z then nil},
8481
+ %q{ ~~~~~~~~ expression (in_pattern.array_pattern)}
8482
+ )
8483
+
8484
+ assert_parses_pattern_match(
8485
+ s(:in_pattern,
8486
+ s(:array_pattern,
8487
+ s(:int, 1),
8488
+ s(:str, 'a'),
8489
+ s(:array_pattern),
8490
+ s(:hash_pattern)),
8491
+ nil,
8492
+ s(:nil)),
8493
+ %q{in 1, "a", [], {} then nil},
8494
+ %q{ ~~~~~~~~~~~~~~ expression (in_pattern.array_pattern)}
8495
+ )
8496
+ end
8497
+
8498
+ def test_pattern_matching_explicit_array_match
8499
+ assert_parses_pattern_match(
8500
+ s(:in_pattern,
8501
+ s(:array_pattern,
8502
+ s(:match_var, :x)),
8503
+ nil,
8504
+ s(:nil)),
8505
+ %q{in [x] then nil},
8506
+ %q{ ~~~ expression (in_pattern.array_pattern)
8507
+ | ~ begin (in_pattern.array_pattern)
8508
+ | ~ end (in_pattern.array_pattern)}
8509
+ )
8510
+
8511
+ assert_parses_pattern_match(
8512
+ s(:in_pattern,
8513
+ s(:array_pattern_with_tail,
8514
+ s(:match_var, :x)),
8515
+ nil,
8516
+ s(:nil)),
8517
+ %q{in [x,] then nil},
8518
+ %q{ ~~~~ expression (in_pattern.array_pattern_with_tail)
8519
+ | ~ begin (in_pattern.array_pattern_with_tail)
8520
+ | ~ end (in_pattern.array_pattern_with_tail)}
8521
+ )
8522
+
8523
+ assert_parses_pattern_match(
8524
+ s(:in_pattern,
8525
+ s(:array_pattern,
8526
+ s(:match_var, :x),
8527
+ s(:match_var, :y)),
8528
+ nil,
8529
+ s(:true)),
8530
+ %q{in [x, y] then true},
8531
+ %q{ ~~~~~~ expression (in_pattern.array_pattern)
8532
+ | ~ begin (in_pattern.array_pattern)
8533
+ | ~ end (in_pattern.array_pattern)}
8534
+ )
8535
+
8536
+ assert_parses_pattern_match(
8537
+ s(:in_pattern,
8538
+ s(:array_pattern_with_tail,
8539
+ s(:match_var, :x),
8540
+ s(:match_var, :y)),
8541
+ nil,
8542
+ s(:true)),
8543
+ %q{in [x, y,] then true},
8544
+ %q{ ~~~~~~~ expression (in_pattern.array_pattern_with_tail)
8545
+ | ~ begin (in_pattern.array_pattern_with_tail)
8546
+ | ~ end (in_pattern.array_pattern_with_tail)}
8547
+ )
8548
+
8549
+ assert_parses_pattern_match(
8550
+ s(:in_pattern,
8551
+ s(:array_pattern,
8552
+ s(:match_var, :x),
8553
+ s(:match_var, :y),
8554
+ s(:match_rest)),
8555
+ nil,
8556
+ s(:true)),
8557
+ %q{in [x, y, *] then true},
8558
+ %q{ ~~~~~~~~~ expression (in_pattern.array_pattern)
8559
+ | ~ begin (in_pattern.array_pattern)
8560
+ | ~ end (in_pattern.array_pattern)}
8561
+ )
8562
+
8563
+ assert_parses_pattern_match(
8564
+ s(:in_pattern,
8565
+ s(:array_pattern,
8566
+ s(:match_var, :x),
8567
+ s(:match_var, :y),
8568
+ s(:match_rest, s(:match_var, :z))),
8569
+ nil,
8570
+ s(:true)),
8571
+ %q{in [x, y, *z] then true},
8572
+ %q{ ~~~~~~~~~~ expression (in_pattern.array_pattern)
8573
+ | ~ begin (in_pattern.array_pattern)
8574
+ | ~ end (in_pattern.array_pattern)}
8575
+ )
8576
+
8577
+ assert_parses_pattern_match(
8578
+ s(:in_pattern,
8579
+ s(:array_pattern,
8580
+ s(:match_var, :x),
8581
+ s(:match_rest, s(:match_var, :y)),
8582
+ s(:match_var, :z)),
8583
+ nil,
8584
+ s(:true)),
8585
+ %q{in [x, *y, z] then true},
8586
+ %q{ ~~~~~~~~~~ expression (in_pattern.array_pattern)
8587
+ | ~ begin (in_pattern.array_pattern)
8588
+ | ~ end (in_pattern.array_pattern)}
8589
+ )
8590
+
8591
+ assert_parses_pattern_match(
8592
+ s(:in_pattern,
8593
+ s(:array_pattern,
8594
+ s(:match_var, :x),
8595
+ s(:match_rest),
8596
+ s(:match_var, :y)),
8597
+ nil,
8598
+ s(:true)),
8599
+ %q{in [x, *, y] then true},
8600
+ %q{ ~~~~~~~~~ expression (in_pattern.array_pattern)
8601
+ | ~ begin (in_pattern.array_pattern)
8602
+ | ~ end (in_pattern.array_pattern)}
8603
+ )
8604
+
8605
+ assert_parses_pattern_match(
8606
+ s(:in_pattern,
8607
+ s(:array_pattern,
8608
+ s(:match_rest, s(:match_var, :x)),
8609
+ s(:match_var, :y)),
8610
+ nil,
8611
+ s(:true)),
8612
+ %q{in [*x, y] then true},
8613
+ %q{ ~~~~~~~ expression (in_pattern.array_pattern)
8614
+ | ~ begin (in_pattern.array_pattern)
8615
+ | ~ end (in_pattern.array_pattern)}
8616
+ )
8617
+
8618
+ assert_parses_pattern_match(
8619
+ s(:in_pattern,
8620
+ s(:array_pattern,
8621
+ s(:match_rest),
8622
+ s(:match_var, :x)),
8623
+ nil,
8624
+ s(:true)),
8625
+ %q{in [*, x] then true},
8626
+ %q{ ~~~~~~ expression (in_pattern.array_pattern)
8627
+ | ~ begin (in_pattern.array_pattern)
8628
+ | ~ end (in_pattern.array_pattern)}
8629
+ )
8630
+ end
8631
+
8632
+ def test_pattern_matching_hash
8633
+ assert_parses_pattern_match(
8634
+ s(:in_pattern,
8635
+ s(:hash_pattern),
8636
+ nil,
8637
+ s(:true)),
8638
+ %q{in {} then true},
8639
+ %q{ ~~ expression (in_pattern.hash_pattern)}
8640
+ )
8641
+
8642
+ assert_parses_pattern_match(
8643
+ s(:in_pattern,
8644
+ s(:hash_pattern,
8645
+ s(:pair, s(:sym, :a), s(:int, 1))),
8646
+ nil,
8647
+ s(:true)),
8648
+ %q{in a: 1 then true},
8649
+ %q{ ~~~~ expression (in_pattern.hash_pattern)}
8650
+ )
8651
+
8652
+ assert_parses_pattern_match(
8653
+ s(:in_pattern,
8654
+ s(:hash_pattern,
8655
+ s(:pair, s(:sym, :a), s(:int, 1))),
8656
+ nil,
8657
+ s(:true)),
8658
+ %q{in { a: 1 } then true},
8659
+ %q{ ~~~~~~~~ expression (in_pattern.hash_pattern)
8660
+ | ~ begin (in_pattern.hash_pattern)
8661
+ | ~ end (in_pattern.hash_pattern)}
8662
+ )
8663
+
8664
+ assert_parses_pattern_match(
8665
+ s(:in_pattern,
8666
+ s(:hash_pattern,
8667
+ s(:match_var, :a)),
8668
+ nil,
8669
+ s(:true)),
8670
+ %q{in a: then true},
8671
+ %q{ ~~ expression (in_pattern.hash_pattern)
8672
+ | ~ name (in_pattern.hash_pattern.match_var)
8673
+ | ~~ expression (in_pattern.hash_pattern.match_var)}
8674
+ )
8675
+
8676
+ assert_parses_pattern_match(
8677
+ s(:in_pattern,
8678
+ s(:hash_pattern,
8679
+ s(:match_rest, s(:match_var, :a))),
8680
+ nil,
8681
+ s(:true)),
8682
+ %q{in **a then true},
8683
+ %q{ ~~~ expression (in_pattern.hash_pattern)
8684
+ | ~~~ expression (in_pattern.hash_pattern.match_rest)
8685
+ | ~~ operator (in_pattern.hash_pattern.match_rest)
8686
+ | ~ expression (in_pattern.hash_pattern.match_rest.match_var)
8687
+ | ~ name (in_pattern.hash_pattern.match_rest.match_var)}
8688
+ )
8689
+
8690
+ assert_parses_pattern_match(
8691
+ s(:in_pattern,
8692
+ s(:hash_pattern,
8693
+ s(:match_rest)),
8694
+ nil,
8695
+ s(:true)),
8696
+ %q{in ** then true},
8697
+ %q{ ~~ expression (in_pattern.hash_pattern)
8698
+ | ~~ expression (in_pattern.hash_pattern.match_rest)
8699
+ | ~~ operator (in_pattern.hash_pattern.match_rest)}
8700
+ )
8701
+
8702
+ assert_parses_pattern_match(
8703
+ s(:in_pattern,
8704
+ s(:hash_pattern,
8705
+ s(:pair, s(:sym, :a), s(:int, 1)),
8706
+ s(:pair, s(:sym, :b), s(:int, 2))),
8707
+ nil,
8708
+ s(:true)),
8709
+ %q{in a: 1, b: 2 then true},
8710
+ %q{ ~~~~~~~~~~ expression (in_pattern.hash_pattern)}
8711
+ )
8712
+
8713
+ assert_parses_pattern_match(
8714
+ s(:in_pattern,
8715
+ s(:hash_pattern,
8716
+ s(:match_var, :a),
8717
+ s(:match_var, :b)),
8718
+ nil,
8719
+ s(:true)),
8720
+ %q{in a:, b: then true},
8721
+ %q{ ~~~~~~ expression (in_pattern.hash_pattern)}
8722
+ )
8723
+
8724
+ assert_parses_pattern_match(
8725
+ s(:in_pattern,
8726
+ s(:hash_pattern,
8727
+ s(:pair, s(:sym, :a), s(:int, 1)),
8728
+ s(:match_var, :_a),
8729
+ s(:match_rest)),
8730
+ nil,
8731
+ s(:true)),
8732
+ %q{in a: 1, _a:, ** then true},
8733
+ %q{ ~~~~~~~~~~~~~ expression (in_pattern.hash_pattern)}
8734
+ )
8735
+ end
8736
+
8737
+ def test_pattern_matching_hash_with_string_keys
8738
+ # Match + assign
8739
+
8740
+ assert_parses_pattern_match(
8741
+ s(:in_pattern,
8742
+ s(:hash_pattern,
8743
+ s(:match_var, :a)),
8744
+ nil,
8745
+ s(:true)),
8746
+ %q{in "a": then true},
8747
+ %q{ ~~~~ expression (in_pattern.hash_pattern.match_var)
8748
+ | ~ name (in_pattern.hash_pattern.match_var)}
8749
+ )
8750
+
8751
+ assert_parses_pattern_match(
8752
+ s(:in_pattern,
8753
+ s(:hash_pattern,
8754
+ s(:match_var, :a)),
8755
+ nil,
8756
+ s(:true)),
8757
+ %q{in "#{ 'a' }": then true},
8758
+ %q{ ~~~~~~~~~~~ expression (in_pattern.hash_pattern.match_var)
8759
+ | ~ name (in_pattern.hash_pattern.match_var)}
8760
+ )
8761
+
8762
+ assert_parses_pattern_match(
8763
+ s(:in_pattern,
8764
+ s(:hash_pattern,
8765
+ s(:match_var, :a)),
8766
+ nil,
8767
+ s(:true)),
8768
+ %q{in "#{ %q{a} }": then true},
8769
+ %q{ ~~~~~~~~~~~~~ expression (in_pattern.hash_pattern.match_var)
8770
+ | ~ name (in_pattern.hash_pattern.match_var)}
8771
+ )
8772
+
8773
+ assert_parses_pattern_match(
8774
+ s(:in_pattern,
8775
+ s(:hash_pattern,
8776
+ s(:match_var, :a)),
8777
+ nil,
8778
+ s(:true)),
8779
+ %q{in "#{ %Q{a} }": then true},
8780
+ %q{ ~~~~~~~~~~~~~ expression (in_pattern.hash_pattern.match_var)
8781
+ | ~ name (in_pattern.hash_pattern.match_var)}
8782
+ )
8783
+
8784
+ # Only match
8785
+
8786
+ assert_parses_pattern_match(
8787
+ s(:in_pattern,
8788
+ s(:hash_pattern,
8789
+ s(:pair, s(:sym, :a), s(:int, 1))),
8790
+ nil,
8791
+ s(:true)),
8792
+ %q{in "a": 1 then true},
8793
+ )
8794
+
8795
+ assert_parses_pattern_match(
8796
+ s(:in_pattern,
8797
+ s(:hash_pattern,
8798
+ s(:pair,
8799
+ s(:dsym, s(:begin, s(:str, "a"))),
8800
+ s(:int, 1))),
8801
+ nil,
8802
+ s(:true)),
8803
+ %q{in "#{ 'a' }": 1 then true},
8804
+ )
8805
+
8806
+ assert_parses_pattern_match(
8807
+ s(:in_pattern,
8808
+ s(:hash_pattern,
8809
+ s(:pair,
8810
+ s(:dsym, s(:begin, s(:str, "a"))),
8811
+ s(:int, 1))),
8812
+ nil,
8813
+ s(:true)),
8814
+ %q{in "#{ %q{a} }": 1 then true},
8815
+ )
8816
+
8817
+ assert_parses_pattern_match(
8818
+ s(:in_pattern,
8819
+ s(:hash_pattern,
8820
+ s(:pair,
8821
+ s(:dsym, s(:begin, s(:str, "a"))),
8822
+ s(:int, 1))),
8823
+ nil,
8824
+ s(:true)),
8825
+ %q{in "#{ %Q{a} }": 1 then true},
8826
+ )
8827
+ end
8828
+
8829
+ def test_pattern_matching_hash_with_heredoc_keys
8830
+ # Ruby <3, the following case is acceptable by the MRI's grammar,
8831
+ # so it has to be reducable by parser.
8832
+ # We have a code for that in the builder.rb that reject it via
8833
+ # diagnostic error because of the wrong lvar name
8834
+ assert_diagnoses(
8835
+ [:error, :lvar_name, { name: "a\n" }],
8836
+ %Q{case nil; in "\#{ <<-HERE }":;\na\nHERE\nelse\nend},
8837
+ %q{ ~~~~~~~ location},
8838
+ SINCE_2_7
8839
+ )
8840
+ end
8841
+
8842
+ def test_pattern_matching_hash_with_string_interpolation_keys
8843
+ assert_diagnoses(
8844
+ [:error, :pm_interp_in_var_name],
8845
+ %q{case a; in "#{a}": 1; end},
8846
+ %q{ ~~~~~~~ location},
8847
+ SINCE_2_7
8848
+ )
8849
+ end
8850
+
8851
+ def test_pattern_matching_keyword_variable
8852
+ assert_parses_pattern_match(
8853
+ s(:in_pattern,
8854
+ s(:self),
8855
+ nil,
8856
+ s(:true)),
8857
+ %q{in self then true}
8858
+ )
8859
+ end
8860
+
8861
+ def test_pattern_matching_lambda
8862
+ assert_parses_pattern_match(
8863
+ s(:in_pattern,
8864
+ s(:block,
8865
+ s(:lambda),
8866
+ s(:args),
8867
+ s(:int, 42)),
8868
+ nil,
8869
+ s(:true)),
8870
+ %q{in ->{ 42 } then true}
8871
+ )
8872
+ end
8873
+
8874
+ def test_pattern_matching_ranges
8875
+ assert_parses_pattern_match(
8876
+ s(:in_pattern,
8877
+ s(:irange, s(:int, 1), s(:int, 2)),
8878
+ nil,
8879
+ s(:true)),
8880
+ %q{in 1..2 then true}
8881
+ )
8882
+
8883
+ assert_parses_pattern_match(
8884
+ s(:in_pattern,
8885
+ s(:irange, s(:int, 1), nil),
8886
+ nil,
8887
+ s(:true)),
8888
+ %q{in 1.. then true}
8889
+ )
8890
+
8891
+ assert_parses_pattern_match(
8892
+ s(:in_pattern,
8893
+ s(:irange, nil, s(:int, 2)),
8894
+ nil,
8895
+ s(:true)),
8896
+ %q{in ..2 then true}
8897
+ )
8898
+
8899
+ assert_parses_pattern_match(
8900
+ s(:in_pattern,
8901
+ s(:erange, s(:int, 1), s(:int, 2)),
8902
+ nil,
8903
+ s(:true)),
8904
+ %q{in 1...2 then true}
8905
+ )
8906
+
8907
+ assert_parses_pattern_match(
8908
+ s(:in_pattern,
8909
+ s(:erange, s(:int, 1), nil),
8910
+ nil,
8911
+ s(:true)),
8912
+ %q{in 1... then true}
8913
+ )
8914
+
8915
+ assert_parses_pattern_match(
8916
+ s(:in_pattern,
8917
+ s(:erange, nil, s(:int, 2)),
8918
+ nil,
8919
+ s(:true)),
8920
+ %q{in ...2 then true}
8921
+ )
8922
+ end
8923
+
8924
+ def test_pattern_matching_expr_in_paren
8925
+ assert_parses_pattern_match(
8926
+ s(:in_pattern,
8927
+ s(:begin, s(:int, 1)),
8928
+ nil,
8929
+ s(:true)),
8930
+ %q{in (1) then true},
8931
+ %q{ ~~~ expression (in_pattern.begin)
8932
+ | ~ begin (in_pattern.begin)
8933
+ | ~ end (in_pattern.begin)}
8934
+ )
8935
+ end
8936
+
8937
+ def test_pattern_matching_constants
8938
+ assert_parses_pattern_match(
8939
+ s(:in_pattern,
8940
+ s(:const, nil, :A),
8941
+ nil,
8942
+ s(:true)),
8943
+ %q{in A then true},
8944
+ %q{ ~ expression (in_pattern.const)
8945
+ | ~ name (in_pattern.const)}
8946
+ )
8947
+
8948
+ assert_parses_pattern_match(
8949
+ s(:in_pattern,
8950
+ s(:const, s(:const, nil, :A), :B),
8951
+ nil,
8952
+ s(:true)),
8953
+ %q{in A::B then true},
8954
+ %q{ ~~~~ expression (in_pattern.const)
8955
+ | ~~ double_colon (in_pattern.const)
8956
+ | ~ name (in_pattern.const)}
8957
+ )
8958
+
8959
+ assert_parses_pattern_match(
8960
+ s(:in_pattern,
8961
+ s(:const, s(:cbase), :A),
8962
+ nil,
8963
+ s(:true)),
8964
+ %q{in ::A then true},
8965
+ %q{ ~~~ expression (in_pattern.const)
8966
+ | ~~ double_colon (in_pattern.const)
8967
+ | ~ name (in_pattern.const)}
8968
+ )
8969
+ end
8970
+
8971
+ def test_pattern_matching_const_pattern
8972
+ assert_parses_pattern_match(
8973
+ s(:in_pattern,
8974
+ s(:const_pattern,
8975
+ s(:const, nil, :A),
8976
+ s(:array_pattern,
8977
+ s(:int, 1),
8978
+ s(:int, 2))),
8979
+ nil,
8980
+ s(:true)),
8981
+ %q{in A(1, 2) then true},
8982
+ %q{ ~~~~~~ expression (in_pattern.const_pattern)
8983
+ | ~ begin (in_pattern.const_pattern)
8984
+ | ~ end (in_pattern.const_pattern)
8985
+ | ~ expression (in_pattern.const_pattern.const)
8986
+ | ~~~~ expression (in_pattern.const_pattern.array_pattern)}
8987
+ )
8988
+
8989
+ assert_parses_pattern_match(
8990
+ s(:in_pattern,
8991
+ s(:const_pattern,
8992
+ s(:const, nil, :A),
8993
+ s(:hash_pattern,
8994
+ s(:match_var, :x))),
8995
+ nil,
8996
+ s(:true)),
8997
+ %q{in A(x:) then true},
8998
+ %q{ ~~~~ expression (in_pattern.const_pattern)
8999
+ | ~ begin (in_pattern.const_pattern)
9000
+ | ~ end (in_pattern.const_pattern)
9001
+ | ~ expression (in_pattern.const_pattern.const)
9002
+ | ~~ expression (in_pattern.const_pattern.hash_pattern)}
9003
+ )
9004
+
9005
+ assert_parses_pattern_match(
9006
+ s(:in_pattern,
9007
+ s(:const_pattern,
9008
+ s(:const, nil, :A),
9009
+ s(:array_pattern)),
9010
+ nil,
9011
+ s(:true)),
9012
+ %q{in A() then true},
9013
+ %q{ ~~ expression (in_pattern.const_pattern)
9014
+ | ~ begin (in_pattern.const_pattern)
9015
+ | ~ end (in_pattern.const_pattern)
9016
+ | ~ expression (in_pattern.const_pattern.const)
9017
+ | ~~ expression (in_pattern.const_pattern.array_pattern)}
9018
+ )
9019
+
9020
+ assert_parses_pattern_match(
9021
+ s(:in_pattern,
9022
+ s(:const_pattern,
9023
+ s(:const, nil, :A),
9024
+ s(:array_pattern,
9025
+ s(:int, 1),
9026
+ s(:int, 2))),
9027
+ nil,
9028
+ s(:true)),
9029
+ %q{in A[1, 2] then true},
9030
+ %q{ ~~~~~~ expression (in_pattern.const_pattern)
9031
+ | ~ begin (in_pattern.const_pattern)
9032
+ | ~ end (in_pattern.const_pattern)
9033
+ | ~ expression (in_pattern.const_pattern.const)
9034
+ | ~~~~ expression (in_pattern.const_pattern.array_pattern)}
9035
+ )
9036
+
9037
+ assert_parses_pattern_match(
9038
+ s(:in_pattern,
9039
+ s(:const_pattern,
9040
+ s(:const, nil, :A),
9041
+ s(:hash_pattern,
9042
+ s(:match_var, :x))),
9043
+ nil,
9044
+ s(:true)),
9045
+ %q{in A[x:] then true},
9046
+ %q{ ~~~~ expression (in_pattern.const_pattern)
9047
+ | ~ begin (in_pattern.const_pattern)
9048
+ | ~ end (in_pattern.const_pattern)
9049
+ | ~ expression (in_pattern.const_pattern.const)
9050
+ | ~~ expression (in_pattern.const_pattern.hash_pattern)}
9051
+ )
9052
+
9053
+ assert_parses_pattern_match(
9054
+ s(:in_pattern,
9055
+ s(:const_pattern,
9056
+ s(:const, nil, :A),
9057
+ s(:array_pattern)),
9058
+ nil,
9059
+ s(:true)),
9060
+ %q{in A[] then true},
9061
+ %q{ ~~ expression (in_pattern.const_pattern)
9062
+ | ~ begin (in_pattern.const_pattern)
9063
+ | ~ end (in_pattern.const_pattern)
9064
+ | ~~ expression (in_pattern.const_pattern.array_pattern)}
9065
+ )
9066
+ end
9067
+
9068
+ def test_pattern_matching_match_alt
9069
+ assert_parses_pattern_match(
9070
+ s(:in_pattern,
9071
+ s(:match_alt, s(:int, 1), s(:int, 2)),
9072
+ nil,
9073
+ s(:true)),
9074
+ %q{in 1 | 2 then true},
9075
+ %q{ ~~~~~ expression (in_pattern.match_alt)
9076
+ | ~ operator (in_pattern.match_alt)}
9077
+ )
9078
+ end
9079
+
9080
+ def test_pattern_matching_match_as
9081
+ assert_parses_pattern_match(
9082
+ s(:in_pattern,
9083
+ s(:match_as,
9084
+ s(:int, 1),
9085
+ s(:match_var, :a)),
9086
+ nil,
9087
+ s(:true)),
9088
+ %q{in 1 => a then true},
9089
+ %q{ ~~~~~~ expression (in_pattern.match_as)
9090
+ | ~~ operator (in_pattern.match_as)}
9091
+ )
9092
+ end
9093
+
9094
+ def test_pattern_matching_else
9095
+ assert_parses(
9096
+ s(:case_match,
9097
+ s(:int, 1),
9098
+ s(:in_pattern,
9099
+ s(:int, 2), nil,
9100
+ s(:int, 3)),
9101
+ s(:int, 4)),
9102
+ %q{case 1; in 2; 3; else; 4; end},
9103
+ %q{ ~~~~ else},
9104
+ SINCE_2_7
9105
+ )
9106
+ end
9107
+
9108
+ def test_pattern_matching_blank_else
9109
+ assert_parses(
9110
+ s(:case_match,
9111
+ s(:int, 1),
9112
+ s(:in_pattern,
9113
+ s(:int, 2), nil,
9114
+ s(:int, 3)),
9115
+ s(:empty_else)),
9116
+ %q{case 1; in 2; 3; else; end},
9117
+ %q{ ~~~~ else},
9118
+ SINCE_2_7
9119
+ )
9120
+ end
9121
+
9122
+ def assert_pattern_matching_defines_local_variables(match_code, lvar_names, versions = SINCE_2_7)
9123
+ code = "case 1; #{match_code}; then [#{lvar_names.join(', ')}]; end"
9124
+
9125
+ with_versions(versions) do |version, parser|
9126
+ source_file = Parser::Source::Buffer.new('(assert_context)')
9127
+ source_file.source = code
9128
+
9129
+ lvar_names.each do |lvar_name|
9130
+ refute parser.static_env.declared?(lvar_name),
9131
+ "(#{version}) local variable #{lvar_name.to_s.inspect} has to be undefined before asserting"
9132
+ end
9133
+
9134
+ before = parser.static_env.instance_variable_get(:@variables).to_a
9135
+
9136
+ begin
9137
+ parsed_ast = parser.parse(source_file)
9138
+ rescue Parser::SyntaxError => exc
9139
+ backtrace = exc.backtrace
9140
+ Exception.instance_method(:initialize).bind(exc).
9141
+ call("(#{version}) #{exc.message}")
9142
+ exc.set_backtrace(backtrace)
9143
+ raise
9144
+ end
9145
+
9146
+ lvar_names.each do |lvar_name|
9147
+ assert parser.static_env.declared?(lvar_name),
9148
+ "(#{version}) expected local variable #{lvar_name.to_s.inspect} to be defined after parsing"
9149
+ end
9150
+
9151
+ after = parser.static_env.instance_variable_get(:@variables).to_a
9152
+ extra = after - before - lvar_names
9153
+
9154
+ assert extra.empty?,
9155
+ "(#{version}) expected only #{lvar_names.inspect} " \
9156
+ "to be defined during parsing, but also got #{extra.inspect}"
9157
+ end
9158
+ end
9159
+
9160
+ def test_pattern_matching_creates_locals
9161
+ assert_pattern_matching_defines_local_variables(
9162
+ %q{in a, *b, c},
9163
+ [:a, :b, :c]
9164
+ )
9165
+
9166
+ assert_pattern_matching_defines_local_variables(
9167
+ %q{in d | e | f},
9168
+ [:d, :e, :f]
9169
+ )
9170
+
9171
+ assert_pattern_matching_defines_local_variables(
9172
+ %q{in { g:, **h }},
9173
+ [:g, :h]
9174
+ )
9175
+
9176
+ assert_pattern_matching_defines_local_variables(
9177
+ %q{in A(i, *j, k)},
9178
+ [:i, :j, :k]
9179
+ )
9180
+
9181
+ assert_pattern_matching_defines_local_variables(
9182
+ %q{in 1 => l},
9183
+ [:l]
9184
+ )
9185
+
9186
+ assert_pattern_matching_defines_local_variables(
9187
+ %q{in "m":},
9188
+ [:m]
9189
+ )
9190
+ end
9191
+
9192
+ def test_pattern_matching__FILE__LINE_literals
9193
+ assert_parses(
9194
+ s(:case_match,
9195
+ s(:array,
9196
+ s(:str, "(assert_parses)"),
9197
+ s(:send,
9198
+ s(:int, 1), :+,
9199
+ s(:int, 1)),
9200
+ s(:__ENCODING__)),
9201
+ s(:in_pattern,
9202
+ s(:array_pattern,
9203
+ s(:str, "(assert_parses)"),
9204
+ s(:int, 2),
9205
+ s(:__ENCODING__)), nil, nil), nil),
9206
+ <<-RUBY,
9207
+ case [__FILE__, __LINE__ + 1, __ENCODING__]
9208
+ in [__FILE__, __LINE__, __ENCODING__]
9209
+ end
9210
+ RUBY
9211
+ %q{},
9212
+ SINCE_2_7)
9213
+ end
9214
+
9215
+ def test_pattern_matching_nil_pattern
9216
+ assert_parses_pattern_match(
9217
+ s(:in_pattern,
9218
+ s(:hash_pattern,
9219
+ s(:match_nil_pattern)),
9220
+ nil,
9221
+ s(:true)),
9222
+ %q{in **nil then true},
9223
+ %q{ ~~~~~ expression (in_pattern.hash_pattern.match_nil_pattern)
9224
+ | ~~~ name (in_pattern.hash_pattern.match_nil_pattern)}
9225
+ )
9226
+ end
9227
+
9228
+ def test_pattern_matching_single_line
9229
+ assert_parses(
9230
+ s(:begin,
9231
+ s(:in_match,
9232
+ s(:int, 1),
9233
+ s(:array_pattern,
9234
+ s(:match_var, :a))),
9235
+ s(:lvar, :a)),
9236
+ %q{1 in [a]; a},
9237
+ %q{~~~~~~~~ expression (in_match)
9238
+ | ~~ operator (in_match)},
9239
+ SINCE_2_7)
9240
+ end
9241
+
9242
+ def test_ruby_bug_pattern_matching_restore_in_kwarg_flag
9243
+ refute_diagnoses(
9244
+ "p(({} in {a:}), a:\n 1)",
9245
+ SINCE_2_7)
9246
+ end
9247
+
9248
+ def test_pattern_matching_duplicate_variable_name
9249
+ assert_diagnoses(
9250
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9251
+ %q{case 0; in a, a; end},
9252
+ %q{ ^ location},
9253
+ SINCE_2_7)
9254
+
9255
+ refute_diagnoses(
9256
+ %q{case [0, 1, 2, 3]; in _, _, _a, _a; end},
9257
+ SINCE_2_7)
9258
+
9259
+ assert_diagnoses(
9260
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9261
+ %q{case 0; in a, {a:}; end},
9262
+ %q{ ^ location},
9263
+ SINCE_2_7)
9264
+
9265
+ assert_diagnoses(
9266
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9267
+ %q{case 0; in a, {"a":}; end},
9268
+ %q{ ^ location},
9269
+ SINCE_2_7)
9270
+
9271
+ assert_diagnoses(
9272
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9273
+ %q{0 in [a, a]},
9274
+ %q{ ^ location},
9275
+ SINCE_2_7)
9276
+ end
9277
+
9278
+ def test_pattern_matching_duplicate_hash_keys
9279
+ assert_diagnoses(
9280
+ [:error, :duplicate_pattern_key, { :name => 'a' }],
9281
+ %q{ case 0; in a: 1, a: 2; end },
9282
+ %q{ ^^ location},
9283
+ SINCE_2_7)
9284
+
9285
+ assert_diagnoses(
9286
+ [:error, :duplicate_pattern_key, { :name => 'a' }],
9287
+ %q{ case 0; in a: 1, "a": 2; end },
9288
+ %q{ ^^^^ location},
9289
+ SINCE_2_7)
9290
+
9291
+ assert_diagnoses(
9292
+ [:error, :duplicate_pattern_key, { :name => 'a' }],
9293
+ %q{ case 0; in "a": 1, "a": 2; end },
9294
+ %q{ ^^^^ location},
9295
+ SINCE_2_7)
9296
+
9297
+ assert_diagnoses(
9298
+ [:error, :duplicate_pattern_key, { :name => "a\0" }],
9299
+ %q{ case 0; in "a\x0":a1, "a\0":a2; end },
9300
+ %q{ ^^^^^^ location},
9301
+ SINCE_2_7)
9302
+
9303
+ assert_diagnoses(
9304
+ [:error, :duplicate_pattern_key, { :name => "abc" }],
9305
+ %q{ case 0; in "abc":a1, "a#{"b"}c":a2; end },
9306
+ %q{ ^^^^^^^^^^^ location},
9307
+ SINCE_2_7)
9308
+ end
9309
+
9310
+ def test_pattern_matching_required_parentheses_for_in_match
9311
+ assert_diagnoses(
9312
+ [:error, :unexpected_token, { :token => 'tCOMMA' }],
9313
+ %{1 in a, b},
9314
+ %{ ^ location},
9315
+ SINCE_2_7)
9316
+
9317
+ assert_diagnoses(
9318
+ [:error, :unexpected_token, { :token => 'tLABEL' }],
9319
+ %{1 in a:},
9320
+ %{ ^^ location},
9321
+ SINCE_2_7)
9322
+ end
9323
+
9324
+ def test_pattern_matching_required_bound_variable_before_pin
9325
+ assert_diagnoses(
9326
+ [:error, :undefined_lvar, { :name => 'a' }],
9327
+ %{case 0; in ^a; true; end},
9328
+ %{ ^ location},
9329
+ SINCE_2_7)
9330
+ end
9331
+
9332
+ def test_parser_bug_645
9333
+ assert_parses(
9334
+ s(:block,
9335
+ s(:lambda),
9336
+ s(:args,
9337
+ s(:optarg, :arg,
9338
+ s(:hash))), nil),
9339
+ '-> (arg={}) {}',
9340
+ %{},
9341
+ SINCE_1_9)
9342
+ end
7579
9343
  end