parser 2.6.5.0 → 2.7.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.5.0'
4
+ VERSION = '2.7.0.0'
5
5
  end
@@ -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
 
@@ -1507,6 +1507,13 @@ class TestLexer < Minitest::Test
1507
1507
  assert_scanned "||", :tOROP, "||", [0, 2]
1508
1508
  end
1509
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
+
1510
1517
  def test_or2_equals
1511
1518
  assert_scanned "||=", :tOP_ASGN, "||", [0, 3]
1512
1519
  end
@@ -3562,51 +3569,6 @@ class TestLexer < Minitest::Test
3562
3569
  :tIDENTIFIER, 're', [1, 3])
3563
3570
  end
3564
3571
 
3565
- def test_meth_ref
3566
- setup_lexer(27)
3567
-
3568
- assert_scanned('foo.:bar',
3569
- :tIDENTIFIER, 'foo', [0, 3],
3570
- :tMETHREF, '.:', [3, 5],
3571
- :tIDENTIFIER, 'bar', [5, 8])
3572
-
3573
- assert_scanned('foo .:bar',
3574
- :tIDENTIFIER, 'foo', [0, 3],
3575
- :tMETHREF, '.:', [4, 6],
3576
- :tIDENTIFIER, 'bar', [6, 9])
3577
- end
3578
-
3579
- def test_meth_ref_unary_op
3580
- setup_lexer(27)
3581
-
3582
- assert_scanned('foo.:+',
3583
- :tIDENTIFIER, 'foo', [0, 3],
3584
- :tMETHREF, '.:', [3, 5],
3585
- :tPLUS, '+', [5, 6])
3586
-
3587
- assert_scanned('foo.:-@',
3588
- :tIDENTIFIER, 'foo', [0, 3],
3589
- :tMETHREF, '.:', [3, 5],
3590
- :tUMINUS, '-@', [5, 7])
3591
- end
3592
-
3593
- def test_meth_ref_unsupported_newlines
3594
- # MRI emits exactly the same sequence of tokens,
3595
- # the error happens later in the parser
3596
-
3597
- assert_scanned('foo. :+',
3598
- :tIDENTIFIER, 'foo', [0, 3],
3599
- :tDOT, '.', [3, 4],
3600
- :tCOLON, ':', [5, 6],
3601
- :tUPLUS, '+', [6, 7])
3602
-
3603
- assert_scanned('foo.: +',
3604
- :tIDENTIFIER, 'foo', [0, 3],
3605
- :tDOT, '.', [3, 4],
3606
- :tCOLON, ':', [4, 5],
3607
- :tPLUS, '+', [6, 7])
3608
- end
3609
-
3610
3572
  def lex_numbered_parameter(input)
3611
3573
  @lex.max_numparam_stack.push
3612
3574
 
@@ -3643,25 +3605,4 @@ class TestLexer < Minitest::Test
3643
3605
  end
3644
3606
  end
3645
3607
 
3646
- def test_numbered_args_before_27
3647
- setup_lexer(26)
3648
- refute_scanned_numbered_parameter('@1')
3649
- end
3650
-
3651
- def test_numbered_args_27
3652
- setup_lexer(27)
3653
- assert_scanned_numbered_parameter('@1')
3654
- assert_equal(@lex.max_numparam, 1)
3655
-
3656
- setup_lexer(27)
3657
- assert_scanned_numbered_parameter('@9')
3658
- assert_equal(@lex.max_numparam, 9)
3659
-
3660
- setup_lexer(27)
3661
- refute_scanned_numbered_parameter('@10', :too_large_numparam)
3662
-
3663
- setup_lexer(27)
3664
- refute_scanned_numbered_parameter('@01', :leading_zero_in_numparam)
3665
- end
3666
-
3667
3608
  end
@@ -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{||})
@@ -7214,52 +7222,6 @@ class TestParser < Minitest::Test
7214
7222
  end
7215
7223
  end
7216
7224
 
7217
- def test_meth_ref__27
7218
- assert_parses(
7219
- s(:meth_ref, s(:lvar, :foo), :bar),
7220
- %q{foo.:bar},
7221
- %q{ ^^ dot
7222
- | ~~~ selector
7223
- |~~~~~~~~ expression},
7224
- SINCE_2_7)
7225
-
7226
- assert_parses(
7227
- s(:meth_ref, s(:lvar, :foo), :+@),
7228
- %q{foo.:+@},
7229
- %q{ ^^ dot
7230
- | ~~ selector
7231
- |~~~~~~~ expression},
7232
- SINCE_2_7)
7233
- end
7234
-
7235
- def test_meth_ref__before_27
7236
- assert_diagnoses(
7237
- [:error, :unexpected_token, { :token => 'tCOLON' }],
7238
- %q{foo.:bar},
7239
- %q{ ^ location },
7240
- ALL_VERSIONS - SINCE_2_7)
7241
-
7242
- assert_diagnoses(
7243
- [:error, :unexpected_token, { :token => 'tCOLON' }],
7244
- %q{foo.:+@},
7245
- %q{ ^ location },
7246
- ALL_VERSIONS - SINCE_2_7)
7247
- end
7248
-
7249
- def test_meth_ref_unsupported_newlines
7250
- assert_diagnoses(
7251
- [:error, :unexpected_token, { :token => 'tCOLON' }],
7252
- %Q{foo. :+},
7253
- %q{ ^ location},
7254
- SINCE_2_7)
7255
-
7256
- assert_diagnoses(
7257
- [:error, :unexpected_token, { :token => 'tCOLON' }],
7258
- %Q{foo.: +},
7259
- %q{ ^ location},
7260
- SINCE_2_7)
7261
- end
7262
-
7263
7225
  def test_unterimated_heredoc_id__27
7264
7226
  assert_diagnoses(
7265
7227
  [:error, :unterminated_heredoc_id],
@@ -7282,29 +7244,20 @@ class TestParser < Minitest::Test
7282
7244
  end
7283
7245
  end
7284
7246
 
7285
- def test_numbered_args_before_27
7286
- assert_diagnoses(
7287
- [:error, :ivar_name, { :name => '@1' }],
7288
- %q{m { @1 }},
7289
- %q{ ^^ location},
7290
- ALL_VERSIONS - SINCE_2_7
7291
- )
7292
- end
7293
-
7294
7247
  def test_numbered_args_after_27
7295
7248
  assert_parses(
7296
7249
  s(:numblock,
7297
7250
  s(:send, nil, :m),
7298
7251
  9,
7299
7252
  s(:send,
7300
- s(:numparam, 1), :+,
7301
- s(:numparam, 9))),
7302
- %q{m { @1 + @9 }},
7253
+ s(:lvar, :_1), :+,
7254
+ s(:lvar, :_9))),
7255
+ %q{m { _1 + _9 }},
7303
7256
  %q{^^^^^^^^^^^^^ expression
7304
- | ^^ name (send/2.numparam/1)
7305
- | ^^ expression (send/2.numparam/1)
7306
- | ^^ name (send/2.numparam/2)
7307
- | ^^ expression (send/2.numparam/2)},
7257
+ | ^^ name (send/2.lvar/1)
7258
+ | ^^ expression (send/2.lvar/1)
7259
+ | ^^ name (send/2.lvar/2)
7260
+ | ^^ expression (send/2.lvar/2)},
7308
7261
  SINCE_2_7)
7309
7262
 
7310
7263
  assert_parses(
@@ -7312,14 +7265,14 @@ class TestParser < Minitest::Test
7312
7265
  s(:send, nil, :m),
7313
7266
  9,
7314
7267
  s(:send,
7315
- s(:numparam, 1), :+,
7316
- s(:numparam, 9))),
7317
- %q{m do @1 + @9 end},
7268
+ s(:lvar, :_1), :+,
7269
+ s(:lvar, :_9))),
7270
+ %q{m do _1 + _9 end},
7318
7271
  %q{^^^^^^^^^^^^^^^^ expression
7319
- | ^^ name (send/2.numparam/1)
7320
- | ^^ expression (send/2.numparam/1)
7321
- | ^^ name (send/2.numparam/2)
7322
- | ^^ expression (send/2.numparam/2)},
7272
+ | ^^ name (send/2.lvar/1)
7273
+ | ^^ expression (send/2.lvar/1)
7274
+ | ^^ name (send/2.lvar/2)
7275
+ | ^^ expression (send/2.lvar/2)},
7323
7276
  SINCE_2_7)
7324
7277
 
7325
7278
  # Lambdas
@@ -7329,14 +7282,14 @@ class TestParser < Minitest::Test
7329
7282
  s(:lambda),
7330
7283
  9,
7331
7284
  s(:send,
7332
- s(:numparam, 1), :+,
7333
- s(:numparam, 9))),
7334
- %q{-> { @1 + @9}},
7285
+ s(:lvar, :_1), :+,
7286
+ s(:lvar, :_9))),
7287
+ %q{-> { _1 + _9}},
7335
7288
  %q{^^^^^^^^^^^^^ expression
7336
- | ^^ name (send.numparam/1)
7337
- | ^^ expression (send.numparam/1)
7338
- | ^^ name (send.numparam/2)
7339
- | ^^ expression (send.numparam/2)},
7289
+ | ^^ name (send.lvar/1)
7290
+ | ^^ expression (send.lvar/1)
7291
+ | ^^ name (send.lvar/2)
7292
+ | ^^ expression (send.lvar/2)},
7340
7293
  SINCE_2_7)
7341
7294
 
7342
7295
  assert_parses(
@@ -7344,14 +7297,14 @@ class TestParser < Minitest::Test
7344
7297
  s(:lambda),
7345
7298
  9,
7346
7299
  s(:send,
7347
- s(:numparam, 1), :+,
7348
- s(:numparam, 9))),
7349
- %q{-> do @1 + @9 end},
7300
+ s(:lvar, :_1), :+,
7301
+ s(:lvar, :_9))),
7302
+ %q{-> do _1 + _9 end},
7350
7303
  %q{^^^^^^^^^^^^^^^^^ expression
7351
- | ^^ name (send.numparam/1)
7352
- | ^^ expression (send.numparam/1)
7353
- | ^^ name (send.numparam/2)
7354
- | ^^ expression (send.numparam/2)},
7304
+ | ^^ name (send.lvar/1)
7305
+ | ^^ expression (send.lvar/1)
7306
+ | ^^ name (send.lvar/2)
7307
+ | ^^ expression (send.lvar/2)},
7355
7308
  SINCE_2_7)
7356
7309
  end
7357
7310
 
@@ -7360,37 +7313,37 @@ class TestParser < Minitest::Test
7360
7313
 
7361
7314
  assert_diagnoses(
7362
7315
  [:error, :ordinary_param_defined],
7363
- %q{m { || @1 } },
7316
+ %q{m { || _1 } },
7364
7317
  %q{ ^^ location},
7365
7318
  SINCE_2_7)
7366
7319
 
7367
7320
  assert_diagnoses(
7368
7321
  [:error, :ordinary_param_defined],
7369
- %q{m { |a| @1 } },
7322
+ %q{m { |a| _1 } },
7370
7323
  %q{ ^^ location},
7371
7324
  SINCE_2_7)
7372
7325
 
7373
7326
  assert_diagnoses(
7374
7327
  [:error, :ordinary_param_defined],
7375
- %q{m do || @1 end },
7328
+ %q{m do || _1 end },
7376
7329
  %q{ ^^ location},
7377
7330
  SINCE_2_7)
7378
7331
 
7379
7332
  assert_diagnoses(
7380
7333
  [:error, :ordinary_param_defined],
7381
- %q{m do |a, b| @1 end },
7334
+ %q{m do |a, b| _1 end },
7382
7335
  %q{ ^^ location},
7383
7336
  SINCE_2_7)
7384
7337
 
7385
7338
  assert_diagnoses(
7386
7339
  [:error, :ordinary_param_defined],
7387
- %q{m { |x = @1| }},
7340
+ %q{m { |x = _1| }},
7388
7341
  %q{ ^^ location},
7389
7342
  SINCE_2_7)
7390
7343
 
7391
7344
  assert_diagnoses(
7392
7345
  [:error, :ordinary_param_defined],
7393
- %q{m { |x: @1| }},
7346
+ %q{m { |x: _1| }},
7394
7347
  %q{ ^^ location},
7395
7348
  SINCE_2_7)
7396
7349
 
@@ -7398,77 +7351,161 @@ class TestParser < Minitest::Test
7398
7351
 
7399
7352
  assert_diagnoses(
7400
7353
  [:error, :ordinary_param_defined],
7401
- %q{->() { @1 } },
7354
+ %q{->() { _1 } },
7402
7355
  %q{ ^^ location},
7403
7356
  SINCE_2_7)
7404
7357
 
7405
7358
  assert_diagnoses(
7406
7359
  [:error, :ordinary_param_defined],
7407
- %q{->(a) { @1 } },
7360
+ %q{->(a) { _1 } },
7408
7361
  %q{ ^^ location},
7409
7362
  SINCE_2_7)
7410
7363
 
7411
7364
  assert_diagnoses(
7412
7365
  [:error, :ordinary_param_defined],
7413
- %q{->() do @1 end },
7366
+ %q{->() do _1 end },
7414
7367
  %q{ ^^ location},
7415
7368
  SINCE_2_7)
7416
7369
 
7417
7370
  assert_diagnoses(
7418
7371
  [:error, :ordinary_param_defined],
7419
- %q{->(a, b) do @1 end},
7372
+ %q{->(a, b) do _1 end},
7420
7373
  %q{ ^^ location},
7421
7374
  SINCE_2_7)
7422
7375
 
7423
7376
  assert_diagnoses(
7424
7377
  [:error, :ordinary_param_defined],
7425
- %q{->(x=@1) {}},
7378
+ %q{->(x=_1) {}},
7426
7379
  %q{ ^^ location},
7427
7380
  SINCE_2_7)
7428
7381
 
7429
7382
  assert_diagnoses(
7430
7383
  [:error, :ordinary_param_defined],
7431
- %q{->(x: @1) {}},
7384
+ %q{->(x: _1) {}},
7432
7385
  %q{ ^^ location},
7433
7386
  SINCE_2_7)
7434
7387
 
7435
7388
  assert_diagnoses(
7436
7389
  [:error, :ordinary_param_defined],
7437
- %q{proc {|;a| @1}},
7390
+ %q{proc {|;a| _1}},
7438
7391
  %q{ ^^ location},
7439
7392
  SINCE_2_7)
7440
7393
 
7441
7394
  assert_diagnoses(
7442
7395
  [:error, :ordinary_param_defined],
7443
- "proc {|\n| @1}",
7396
+ "proc {|\n| _1}",
7444
7397
  %q{ ^^ location},
7445
7398
  SINCE_2_7)
7446
7399
  end
7447
7400
 
7448
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
+
7449
7453
  assert_diagnoses(
7450
- [:error, :numparam_outside_block],
7451
- %q{class A; @1; end},
7452
- %q{ ^^ location},
7454
+ [:error, :cant_assign_to_numparam, { :name => '_1' }],
7455
+ %q{proc {_1; _1 = nil}},
7456
+ %q{ ^^ location},
7453
7457
  SINCE_2_7)
7454
7458
 
7455
7459
  assert_diagnoses(
7456
- [:error, :numparam_outside_block],
7457
- %q{module A; @1; end},
7460
+ [:error, :cant_assign_to_numparam, { :name => '_1' }],
7461
+ %q{proc {_1; _1, foo = [nil, nil]}},
7458
7462
  %q{ ^^ location},
7459
7463
  SINCE_2_7)
7460
7464
 
7461
7465
  assert_diagnoses(
7462
- [:error, :numparam_outside_block],
7463
- %q{class << foo; @1; end},
7464
- %q{ ^^ location},
7466
+ [:error, :cant_assign_to_numparam, { :name => '_1' }],
7467
+ %q{proc {_9; _1 = nil}},
7468
+ %q{ ^^ location},
7465
7469
  SINCE_2_7)
7466
7470
 
7467
7471
  assert_diagnoses(
7468
- [:error, :numparam_outside_block],
7469
- %q{def self.m; @1; end},
7470
- %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},
7471
7487
  SINCE_2_7)
7488
+
7489
+ assert_diagnoses(
7490
+ [:error, :numparam_used_in_outer_scope],
7491
+ %q{-> { _1; -> { _2 }; }},
7492
+ %q{ ^^ location},
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
7472
7509
  end
7473
7510
 
7474
7511
  def test_ruby_bug_15789
@@ -7480,9 +7517,9 @@ class TestParser < Minitest::Test
7480
7517
  s(:optarg, :a,
7481
7518
  s(:numblock,
7482
7519
  s(:lambda), 1,
7483
- s(:numparam, 1)))),
7520
+ s(:lvar, :_1)))),
7484
7521
  s(:lvar, :a))),
7485
- %q{m ->(a = ->{@1}) {a}},
7522
+ %q{m ->(a = ->{_1}) {a}},
7486
7523
  %q{},
7487
7524
  SINCE_2_7)
7488
7525
 
@@ -7494,9 +7531,9 @@ class TestParser < Minitest::Test
7494
7531
  s(:kwoptarg, :a,
7495
7532
  s(:numblock,
7496
7533
  s(:lambda), 1,
7497
- s(:numparam, 1)))),
7534
+ s(:lvar, :_1)))),
7498
7535
  s(:lvar, :a))),
7499
- %q{m ->(a: ->{@1}) {a}},
7536
+ %q{m ->(a: ->{_1}) {a}},
7500
7537
  %q{},
7501
7538
  SINCE_2_7)
7502
7539
  end
@@ -7613,13 +7650,6 @@ class TestParser < Minitest::Test
7613
7650
  %Q{a #\n#\n&.foo\n},
7614
7651
  %q{},
7615
7652
  SINCE_2_7)
7616
-
7617
- assert_parses(
7618
- s(:meth_ref,
7619
- s(:send, nil, :a), :foo),
7620
- %Q{a #\n#\n.:foo\n},
7621
- %q{},
7622
- SINCE_2_7)
7623
7653
  end
7624
7654
 
7625
7655
  def test_comments_before_leading_dot__before_27
@@ -7641,4 +7671,1627 @@ class TestParser < Minitest::Test
7641
7671
  %q{ ^ location},
7642
7672
  ALL_VERSIONS - SINCE_2_7)
7643
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_keyword_variable
8843
+ assert_parses_pattern_match(
8844
+ s(:in_pattern,
8845
+ s(:self),
8846
+ nil,
8847
+ s(:true)),
8848
+ %q{in self then true}
8849
+ )
8850
+ end
8851
+
8852
+ def test_pattern_matching_lambda
8853
+ assert_parses_pattern_match(
8854
+ s(:in_pattern,
8855
+ s(:block,
8856
+ s(:lambda),
8857
+ s(:args),
8858
+ s(:int, 42)),
8859
+ nil,
8860
+ s(:true)),
8861
+ %q{in ->{ 42 } then true}
8862
+ )
8863
+ end
8864
+
8865
+ def test_pattern_matching_ranges
8866
+ assert_parses_pattern_match(
8867
+ s(:in_pattern,
8868
+ s(:irange, s(:int, 1), s(:int, 2)),
8869
+ nil,
8870
+ s(:true)),
8871
+ %q{in 1..2 then true}
8872
+ )
8873
+
8874
+ assert_parses_pattern_match(
8875
+ s(:in_pattern,
8876
+ s(:irange, s(:int, 1), nil),
8877
+ nil,
8878
+ s(:true)),
8879
+ %q{in 1.. then true}
8880
+ )
8881
+
8882
+ assert_parses_pattern_match(
8883
+ s(:in_pattern,
8884
+ s(:irange, nil, s(:int, 2)),
8885
+ nil,
8886
+ s(:true)),
8887
+ %q{in ..2 then true}
8888
+ )
8889
+
8890
+ assert_parses_pattern_match(
8891
+ s(:in_pattern,
8892
+ s(:erange, s(:int, 1), s(:int, 2)),
8893
+ nil,
8894
+ s(:true)),
8895
+ %q{in 1...2 then true}
8896
+ )
8897
+
8898
+ assert_parses_pattern_match(
8899
+ s(:in_pattern,
8900
+ s(:erange, s(:int, 1), nil),
8901
+ nil,
8902
+ s(:true)),
8903
+ %q{in 1... then true}
8904
+ )
8905
+
8906
+ assert_parses_pattern_match(
8907
+ s(:in_pattern,
8908
+ s(:erange, nil, s(:int, 2)),
8909
+ nil,
8910
+ s(:true)),
8911
+ %q{in ...2 then true}
8912
+ )
8913
+ end
8914
+
8915
+ def test_pattern_matching_expr_in_paren
8916
+ assert_parses_pattern_match(
8917
+ s(:in_pattern,
8918
+ s(:begin, s(:int, 1)),
8919
+ nil,
8920
+ s(:true)),
8921
+ %q{in (1) then true},
8922
+ %q{ ~~~ expression (in_pattern.begin)
8923
+ | ~ begin (in_pattern.begin)
8924
+ | ~ end (in_pattern.begin)}
8925
+ )
8926
+ end
8927
+
8928
+ def test_pattern_matching_constants
8929
+ assert_parses_pattern_match(
8930
+ s(:in_pattern,
8931
+ s(:const, nil, :A),
8932
+ nil,
8933
+ s(:true)),
8934
+ %q{in A then true},
8935
+ %q{ ~ expression (in_pattern.const)
8936
+ | ~ name (in_pattern.const)}
8937
+ )
8938
+
8939
+ assert_parses_pattern_match(
8940
+ s(:in_pattern,
8941
+ s(:const, s(:const, nil, :A), :B),
8942
+ nil,
8943
+ s(:true)),
8944
+ %q{in A::B then true},
8945
+ %q{ ~~~~ expression (in_pattern.const)
8946
+ | ~~ double_colon (in_pattern.const)
8947
+ | ~ name (in_pattern.const)}
8948
+ )
8949
+
8950
+ assert_parses_pattern_match(
8951
+ s(:in_pattern,
8952
+ s(:const, s(:cbase), :A),
8953
+ nil,
8954
+ s(:true)),
8955
+ %q{in ::A then true},
8956
+ %q{ ~~~ expression (in_pattern.const)
8957
+ | ~~ double_colon (in_pattern.const)
8958
+ | ~ name (in_pattern.const)}
8959
+ )
8960
+ end
8961
+
8962
+ def test_pattern_matching_const_pattern
8963
+ assert_parses_pattern_match(
8964
+ s(:in_pattern,
8965
+ s(:const_pattern,
8966
+ s(:const, nil, :A),
8967
+ s(:array_pattern,
8968
+ s(:int, 1),
8969
+ s(:int, 2))),
8970
+ nil,
8971
+ s(:true)),
8972
+ %q{in A(1, 2) then true},
8973
+ %q{ ~~~~~~ expression (in_pattern.const_pattern)
8974
+ | ~ begin (in_pattern.const_pattern)
8975
+ | ~ end (in_pattern.const_pattern)
8976
+ | ~ expression (in_pattern.const_pattern.const)
8977
+ | ~~~~ expression (in_pattern.const_pattern.array_pattern)}
8978
+ )
8979
+
8980
+ assert_parses_pattern_match(
8981
+ s(:in_pattern,
8982
+ s(:const_pattern,
8983
+ s(:const, nil, :A),
8984
+ s(:hash_pattern,
8985
+ s(:match_var, :x))),
8986
+ nil,
8987
+ s(:true)),
8988
+ %q{in A(x:) then true},
8989
+ %q{ ~~~~ expression (in_pattern.const_pattern)
8990
+ | ~ begin (in_pattern.const_pattern)
8991
+ | ~ end (in_pattern.const_pattern)
8992
+ | ~ expression (in_pattern.const_pattern.const)
8993
+ | ~~ expression (in_pattern.const_pattern.hash_pattern)}
8994
+ )
8995
+
8996
+ assert_parses_pattern_match(
8997
+ s(:in_pattern,
8998
+ s(:const_pattern,
8999
+ s(:const, nil, :A),
9000
+ nil),
9001
+ nil,
9002
+ s(:true)),
9003
+ %q{in A() then true},
9004
+ %q{ ~~ expression (in_pattern.const_pattern)
9005
+ | ~ begin (in_pattern.const_pattern)
9006
+ | ~ end (in_pattern.const_pattern)}
9007
+ )
9008
+
9009
+ assert_parses_pattern_match(
9010
+ s(:in_pattern,
9011
+ s(:const_pattern,
9012
+ s(:const, nil, :A),
9013
+ s(:array_pattern,
9014
+ s(:int, 1),
9015
+ s(:int, 2))),
9016
+ nil,
9017
+ s(:true)),
9018
+ %q{in A[1, 2] then true},
9019
+ %q{ ~~~~~~ expression (in_pattern.const_pattern)
9020
+ | ~ begin (in_pattern.const_pattern)
9021
+ | ~ end (in_pattern.const_pattern)
9022
+ | ~ expression (in_pattern.const_pattern.const)
9023
+ | ~~~~ expression (in_pattern.const_pattern.array_pattern)}
9024
+ )
9025
+
9026
+ assert_parses_pattern_match(
9027
+ s(:in_pattern,
9028
+ s(:const_pattern,
9029
+ s(:const, nil, :A),
9030
+ s(:hash_pattern,
9031
+ s(:match_var, :x))),
9032
+ nil,
9033
+ s(:true)),
9034
+ %q{in A[x:] then true},
9035
+ %q{ ~~~~ expression (in_pattern.const_pattern)
9036
+ | ~ begin (in_pattern.const_pattern)
9037
+ | ~ end (in_pattern.const_pattern)
9038
+ | ~ expression (in_pattern.const_pattern.const)
9039
+ | ~~ expression (in_pattern.const_pattern.hash_pattern)}
9040
+ )
9041
+
9042
+ assert_parses_pattern_match(
9043
+ s(:in_pattern,
9044
+ s(:const_pattern,
9045
+ s(:const, nil, :A),
9046
+ nil),
9047
+ nil,
9048
+ s(:true)),
9049
+ %q{in A[] then true},
9050
+ %q{ ~~ expression (in_pattern.const_pattern)
9051
+ | ~ begin (in_pattern.const_pattern)
9052
+ | ~ end (in_pattern.const_pattern)}
9053
+ )
9054
+ end
9055
+
9056
+ def test_pattern_matching_match_alt
9057
+ assert_parses_pattern_match(
9058
+ s(:in_pattern,
9059
+ s(:match_alt, s(:int, 1), s(:int, 2)),
9060
+ nil,
9061
+ s(:true)),
9062
+ %q{in 1 | 2 then true},
9063
+ %q{ ~~~~~ expression (in_pattern.match_alt)
9064
+ | ~ operator (in_pattern.match_alt)}
9065
+ )
9066
+ end
9067
+
9068
+ def test_pattern_matching_match_as
9069
+ assert_parses_pattern_match(
9070
+ s(:in_pattern,
9071
+ s(:match_as,
9072
+ s(:int, 1),
9073
+ s(:match_var, :a)),
9074
+ nil,
9075
+ s(:true)),
9076
+ %q{in 1 => a then true},
9077
+ %q{ ~~~~~~ expression (in_pattern.match_as)
9078
+ | ~~ operator (in_pattern.match_as)}
9079
+ )
9080
+ end
9081
+
9082
+ def test_pattern_matching_else
9083
+ assert_parses(
9084
+ s(:case_match,
9085
+ s(:int, 1),
9086
+ s(:in_pattern,
9087
+ s(:int, 2), nil,
9088
+ s(:int, 3)),
9089
+ s(:int, 4)),
9090
+ %q{case 1; in 2; 3; else; 4; end},
9091
+ %q{ ~~~~ else},
9092
+ SINCE_2_7
9093
+ )
9094
+ end
9095
+
9096
+ def assert_pattern_matching_defines_local_variables(match_code, lvar_names, versions = SINCE_2_7)
9097
+ code = "case 1; #{match_code}; then [#{lvar_names.join(', ')}]; end"
9098
+
9099
+ with_versions(versions) do |version, parser|
9100
+ source_file = Parser::Source::Buffer.new('(assert_context)')
9101
+ source_file.source = code
9102
+
9103
+ lvar_names.each do |lvar_name|
9104
+ refute parser.static_env.declared?(lvar_name),
9105
+ "(#{version}) local variable #{lvar_name.to_s.inspect} has to be undefined before asserting"
9106
+ end
9107
+
9108
+ before = parser.static_env.instance_variable_get(:@variables).to_a
9109
+
9110
+ begin
9111
+ parsed_ast = parser.parse(source_file)
9112
+ rescue Parser::SyntaxError => exc
9113
+ backtrace = exc.backtrace
9114
+ Exception.instance_method(:initialize).bind(exc).
9115
+ call("(#{version}) #{exc.message}")
9116
+ exc.set_backtrace(backtrace)
9117
+ raise
9118
+ end
9119
+
9120
+ lvar_names.each do |lvar_name|
9121
+ assert parser.static_env.declared?(lvar_name),
9122
+ "(#{version}) expected local variable #{lvar_name.to_s.inspect} to be defined after parsing"
9123
+ end
9124
+
9125
+ after = parser.static_env.instance_variable_get(:@variables).to_a
9126
+ extra = after - before - lvar_names
9127
+
9128
+ assert extra.empty?,
9129
+ "(#{version}) expected only #{lvar_names.inspect} " \
9130
+ "to be defined during parsing, but also got #{extra.inspect}"
9131
+ end
9132
+ end
9133
+
9134
+ def test_pattern_matching_creates_locals
9135
+ assert_pattern_matching_defines_local_variables(
9136
+ %q{in a, *b, c},
9137
+ [:a, :b, :c]
9138
+ )
9139
+
9140
+ assert_pattern_matching_defines_local_variables(
9141
+ %q{in d | e | f},
9142
+ [:d, :e, :f]
9143
+ )
9144
+
9145
+ assert_pattern_matching_defines_local_variables(
9146
+ %q{in { g:, **h }},
9147
+ [:g, :h]
9148
+ )
9149
+
9150
+ assert_pattern_matching_defines_local_variables(
9151
+ %q{in A(i, *j, k)},
9152
+ [:i, :j, :k]
9153
+ )
9154
+
9155
+ assert_pattern_matching_defines_local_variables(
9156
+ %q{in 1 => l},
9157
+ [:l]
9158
+ )
9159
+
9160
+ assert_pattern_matching_defines_local_variables(
9161
+ %q{in "m":},
9162
+ [:m]
9163
+ )
9164
+ end
9165
+
9166
+ def test_pattern_matching__FILE__LINE_literals
9167
+ assert_parses(
9168
+ s(:case_match,
9169
+ s(:array,
9170
+ s(:str, "(assert_parses)"),
9171
+ s(:send,
9172
+ s(:int, 1), :+,
9173
+ s(:int, 1)),
9174
+ s(:__ENCODING__)),
9175
+ s(:in_pattern,
9176
+ s(:array_pattern,
9177
+ s(:str, "(assert_parses)"),
9178
+ s(:int, 2),
9179
+ s(:__ENCODING__)), nil, nil), nil),
9180
+ <<-RUBY,
9181
+ case [__FILE__, __LINE__ + 1, __ENCODING__]
9182
+ in [__FILE__, __LINE__, __ENCODING__]
9183
+ end
9184
+ RUBY
9185
+ %q{},
9186
+ SINCE_2_7)
9187
+ end
9188
+
9189
+ def test_pattern_matching_nil_pattern
9190
+ assert_parses_pattern_match(
9191
+ s(:in_pattern,
9192
+ s(:hash_pattern,
9193
+ s(:match_nil_pattern)),
9194
+ nil,
9195
+ s(:true)),
9196
+ %q{in **nil then true},
9197
+ %q{ ~~~~~ expression (in_pattern.hash_pattern.match_nil_pattern)
9198
+ | ~~~ name (in_pattern.hash_pattern.match_nil_pattern)}
9199
+ )
9200
+ end
9201
+
9202
+ def test_pattern_matching_single_line
9203
+ assert_parses(
9204
+ s(:begin,
9205
+ s(:in_match,
9206
+ s(:int, 1),
9207
+ s(:array_pattern,
9208
+ s(:match_var, :a))),
9209
+ s(:lvar, :a)),
9210
+ %q{1 in [a]; a},
9211
+ %q{~~~~~~~~ expression (in_match)
9212
+ | ~~ operator (in_match)},
9213
+ SINCE_2_7)
9214
+ end
9215
+
9216
+ def test_ruby_bug_pattern_matching_restore_in_kwarg_flag
9217
+ refute_diagnoses(
9218
+ "p(({} in {a:}), a:\n 1)",
9219
+ SINCE_2_7)
9220
+ end
9221
+
9222
+ def test_pattern_matching_duplicate_variable_name
9223
+ assert_diagnoses(
9224
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9225
+ %q{case 0; in a, a; end},
9226
+ %q{ ^ location},
9227
+ SINCE_2_7)
9228
+
9229
+ refute_diagnoses(
9230
+ %q{case [0, 1, 2, 3]; in _, _, _a, _a; end},
9231
+ SINCE_2_7)
9232
+
9233
+ assert_diagnoses(
9234
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9235
+ %q{case 0; in a, {a:}; end},
9236
+ %q{ ^ location},
9237
+ SINCE_2_7)
9238
+
9239
+ assert_diagnoses(
9240
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9241
+ %q{case 0; in a, {"a":}; end},
9242
+ %q{ ^ location},
9243
+ SINCE_2_7)
9244
+
9245
+ assert_diagnoses(
9246
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9247
+ %q{0 in [a, a]},
9248
+ %q{ ^ location},
9249
+ SINCE_2_7)
9250
+ end
9251
+
9252
+ def test_pattern_matching_duplicate_hash_keys
9253
+ assert_diagnoses(
9254
+ [:error, :duplicate_pattern_key, { :name => 'a' }],
9255
+ %q{ case 0; in a: 1, a: 2; end },
9256
+ %q{ ^^ location},
9257
+ SINCE_2_7)
9258
+
9259
+ assert_diagnoses(
9260
+ [:error, :duplicate_pattern_key, { :name => 'a' }],
9261
+ %q{ case 0; in a: 1, "a": 2; end },
9262
+ %q{ ^^^^ location},
9263
+ SINCE_2_7)
9264
+
9265
+ assert_diagnoses(
9266
+ [:error, :duplicate_pattern_key, { :name => 'a' }],
9267
+ %q{ case 0; in "a": 1, "a": 2; end },
9268
+ %q{ ^^^^ location},
9269
+ SINCE_2_7)
9270
+
9271
+ assert_diagnoses(
9272
+ [:error, :duplicate_pattern_key, { :name => "a\0" }],
9273
+ %q{ case 0; in "a\x0":a1, "a\0":a2; end },
9274
+ %q{ ^^^^^^ location},
9275
+ SINCE_2_7)
9276
+
9277
+ assert_diagnoses(
9278
+ [:error, :duplicate_pattern_key, { :name => "abc" }],
9279
+ %q{ case 0; in "abc":a1, "a#{"b"}c":a2; end },
9280
+ %q{ ^^^^^^^^^^^ location},
9281
+ SINCE_2_7)
9282
+ end
9283
+
9284
+ def test_pattern_matching_required_parentheses_for_in_match
9285
+ assert_diagnoses(
9286
+ [:error, :unexpected_token, { :token => 'tCOMMA' }],
9287
+ %{1 in a, b},
9288
+ %{ ^ location},
9289
+ SINCE_2_7)
9290
+
9291
+ assert_diagnoses(
9292
+ [:error, :unexpected_token, { :token => 'tLABEL' }],
9293
+ %{1 in a:},
9294
+ %{ ^^ location},
9295
+ SINCE_2_7)
9296
+ end
7644
9297
  end