parser 2.6.5.0 → 2.7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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