parser 2.6.5.0 → 2.7.0.4

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.
@@ -56,11 +56,11 @@ module Parser
56
56
  if action.range == @range
57
57
  merge(action)
58
58
  else
59
- place_in_hierachy(action)
59
+ place_in_hierarchy(action)
60
60
  end
61
61
  end
62
62
 
63
- def place_in_hierachy(action)
63
+ def place_in_hierarchy(action)
64
64
  family = @children.group_by { |child| child.relationship_with(action) }
65
65
 
66
66
  if family[:fusible]
@@ -3,6 +3,8 @@
3
3
  module Parser
4
4
 
5
5
  class StaticEnvironment
6
+ FORWARD_ARGS = :FORWARD_ARGS
7
+
6
8
  def initialize
7
9
  reset
8
10
  end
@@ -41,6 +43,14 @@ module Parser
41
43
  def declared?(name)
42
44
  @variables.include?(name.to_sym)
43
45
  end
46
+
47
+ def declare_forward_args
48
+ declare(FORWARD_ARGS)
49
+ end
50
+
51
+ def declared_forward_args?
52
+ declared?(FORWARD_ARGS)
53
+ end
44
54
  end
45
55
 
46
56
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Parser
4
+
5
+ class VariablesStack
6
+ def initialize
7
+ @stack = []
8
+ push
9
+ end
10
+
11
+ def push
12
+ @stack << Set.new
13
+ end
14
+
15
+ def pop
16
+ @stack.pop
17
+ end
18
+
19
+ def reset
20
+ @stack.clear
21
+ end
22
+
23
+ def declare(name)
24
+ @stack.last << name.to_sym
25
+ end
26
+
27
+ def declared?(name)
28
+ @stack.last.include?(name.to_sym)
29
+ end
30
+ end
31
+
32
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parser
4
- VERSION = '2.6.5.0'
4
+ VERSION = '2.7.0.4'
5
5
  end
@@ -13,6 +13,13 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = 'https://github.com/whitequark/parser'
14
14
  spec.license = 'MIT'
15
15
 
16
+ spec.metadata = {
17
+ 'bug_tracker_uri' => 'https://github.com/whitequark/parser/issues',
18
+ 'changelog_uri' => "https://github.com/whitequark/parser/blob/v#{spec.version}/CHANGELOG.md",
19
+ 'documentation_uri' => "https://www.rubydoc.info/gems/parser/#{spec.version}",
20
+ 'source_code_uri' => "https://github.com/whitequark/parser/tree/v#{spec.version}"
21
+ }
22
+
16
23
  spec.files = `git ls-files`.split + %w(
17
24
  lib/parser/lexer.rb
18
25
  lib/parser/ruby18.rb
@@ -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
 
@@ -127,6 +127,9 @@ module ParseHelper
127
127
 
128
128
  assert parser.instance_eval { @lexer }.cmdarg.empty?,
129
129
  "(#{version}) expected cmdarg to be empty after parsing"
130
+
131
+ assert_equal 0, parser.instance_eval { @lexer.instance_eval { @paren_nest } },
132
+ "(#{version}) expected paren_nest to be 0 after parsing"
130
133
  end
131
134
 
132
135
  # Use like this:
@@ -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
@@ -7607,6 +7644,13 @@ class TestParser < Minitest::Test
7607
7644
  %q{},
7608
7645
  SINCE_2_7)
7609
7646
 
7647
+ assert_parses(
7648
+ s(:send,
7649
+ s(:send, nil, :a), :foo),
7650
+ %Q{a #\n #\n.foo\n},
7651
+ %q{},
7652
+ SINCE_2_7)
7653
+
7610
7654
  assert_parses(
7611
7655
  s(:csend,
7612
7656
  s(:send, nil, :a), :foo),
@@ -7615,9 +7659,9 @@ class TestParser < Minitest::Test
7615
7659
  SINCE_2_7)
7616
7660
 
7617
7661
  assert_parses(
7618
- s(:meth_ref,
7662
+ s(:csend,
7619
7663
  s(:send, nil, :a), :foo),
7620
- %Q{a #\n#\n.:foo\n},
7664
+ %Q{a #\n #\n&.foo\n},
7621
7665
  %q{},
7622
7666
  SINCE_2_7)
7623
7667
  end
@@ -7641,4 +7685,1673 @@ class TestParser < Minitest::Test
7641
7685
  %q{ ^ location},
7642
7686
  ALL_VERSIONS - SINCE_2_7)
7643
7687
  end
7688
+
7689
+ def test_circular_argument_reference_error
7690
+ assert_diagnoses(
7691
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7692
+ %q{def m(foo = foo) end},
7693
+ %q{ ^^^ location},
7694
+ SINCE_2_7)
7695
+
7696
+ assert_diagnoses(
7697
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7698
+ %q{def m(foo: foo) end},
7699
+ %q{ ^^^ location},
7700
+ SINCE_2_7)
7701
+
7702
+ assert_diagnoses(
7703
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7704
+ %q{m { |foo = foo| } },
7705
+ %q{ ^^^ location},
7706
+ SINCE_2_7)
7707
+
7708
+ assert_diagnoses(
7709
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7710
+ %q{m { |foo: foo| } },
7711
+ %q{ ^^^ location},
7712
+ SINCE_2_7)
7713
+
7714
+ # Traversing
7715
+
7716
+ assert_diagnoses(
7717
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7718
+ %q{def m(foo = class << foo; end) end},
7719
+ %q{ ^^^ location},
7720
+ SINCE_2_7)
7721
+
7722
+ assert_diagnoses(
7723
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7724
+ %q{def m(foo = def foo.m; end); end},
7725
+ %q{ ^^^ location},
7726
+ SINCE_2_7)
7727
+
7728
+ assert_diagnoses(
7729
+ [:error, :circular_argument_reference, { :var_name => 'foo' }],
7730
+ %q{m { |foo = proc { 1 + foo }| } },
7731
+ %q{ ^^^ location},
7732
+ SINCE_2_7)
7733
+
7734
+ # Valid cases
7735
+
7736
+ [
7737
+ 'm { |foo = class A; foo; end| }',
7738
+ 'm { |foo = class << self; foo; end| }',
7739
+ 'm { |foo = def m(foo = bar); foo; end| }',
7740
+ 'm { |foo = def m(bar = foo); foo; end| }',
7741
+ 'm { |foo = def self.m(bar = foo); foo; end| }',
7742
+ 'def m(foo = def m; foo; end) end',
7743
+ 'def m(foo = def self.m; foo; end) end',
7744
+ 'm { |foo = proc { |bar| 1 + foo }| }',
7745
+ 'm { |foo = proc { || 1 + foo }| }'
7746
+ ].each do |code|
7747
+ refute_diagnoses(code, SINCE_2_7)
7748
+ end
7749
+ end
7750
+
7751
+ def test_forward_args
7752
+ assert_parses(
7753
+ s(:def, :foo,
7754
+ s(:forward_args),
7755
+ s(:send, nil, :bar,
7756
+ s(:forwarded_args))),
7757
+ %q{def foo(...); bar(...); end},
7758
+ %q{ ~ begin (forward_args)
7759
+ | ~~~~~ expression (forward_args)
7760
+ | ~ end (forward_args)
7761
+ | ~~~ expression (send.forwarded_args)},
7762
+ SINCE_2_7)
7763
+
7764
+ assert_parses(
7765
+ s(:def, :foo,
7766
+ s(:forward_args),
7767
+ s(:super,
7768
+ s(:forwarded_args))),
7769
+ %q{def foo(...); super(...); end},
7770
+ %q{ ~ begin (forward_args)
7771
+ | ~~~~~ expression (forward_args)
7772
+ | ~ end (forward_args)
7773
+ | ~~~ expression (super.forwarded_args)},
7774
+ SINCE_2_7)
7775
+
7776
+ assert_parses(
7777
+ s(:def, :foo,
7778
+ s(:forward_args),
7779
+ nil),
7780
+ %q{def foo(...); end},
7781
+ %q{},
7782
+ SINCE_2_7)
7783
+
7784
+ assert_diagnoses(
7785
+ [:error, :block_and_blockarg],
7786
+ %q{def foo(...) bar(...) { }; end},
7787
+ %q{ ^^^ location
7788
+ | ~ highlights (0)},
7789
+ SINCE_2_7)
7790
+
7791
+ assert_diagnoses(
7792
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7793
+ %q{foo do |...| end},
7794
+ %q{ ^^^ location},
7795
+ SINCE_2_7)
7796
+
7797
+ assert_diagnoses(
7798
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7799
+ %q{foo { |...| }},
7800
+ %q{ ^^^ location},
7801
+ SINCE_2_7)
7802
+
7803
+ assert_diagnoses(
7804
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7805
+ %q{def foo(x,y,z); bar(...); end},
7806
+ %q{ ^^^ location},
7807
+ SINCE_2_7)
7808
+
7809
+ assert_diagnoses(
7810
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7811
+ %q{def foo(x,y,z); super(...); end},
7812
+ %q{ ^^^ location},
7813
+ SINCE_2_7)
7814
+
7815
+ assert_diagnoses(
7816
+ [:error, :unexpected_token, { :token => 'tDOT3' }],
7817
+ %q{->... {}},
7818
+ %q{ ^^^ location},
7819
+ SINCE_2_7)
7820
+
7821
+ assert_diagnoses(
7822
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7823
+ %q{->(...) {}},
7824
+ %q{ ^^^ location},
7825
+ SINCE_2_7)
7826
+
7827
+ # Here and below the parser asssumes that
7828
+ # it can be a beginningless range, so the error comes after reducing right paren
7829
+ assert_diagnoses(
7830
+ [:error, :unexpected_token, { :token => 'tRPAREN' }],
7831
+ %q{def foo(...); yield(...); end},
7832
+ %q{ ^ location},
7833
+ SINCE_2_7)
7834
+
7835
+ assert_diagnoses(
7836
+ [:error, :unexpected_token, { :token => 'tRPAREN' }],
7837
+ %q{def foo(...); return(...); end},
7838
+ %q{ ^ location},
7839
+ SINCE_2_7)
7840
+
7841
+ assert_diagnoses(
7842
+ [:error, :unexpected_token, { :token => 'tRPAREN' }],
7843
+ %q{def foo(...); a = (...); end},
7844
+ %q{ ^ location},
7845
+ SINCE_2_7)
7846
+
7847
+ assert_diagnoses(
7848
+ [:error, :unexpected_token, { :token => 'tRBRACK' }],
7849
+ %q{def foo(...); [...]; end},
7850
+ %q{ ^ location},
7851
+ SINCE_2_7)
7852
+
7853
+ assert_diagnoses(
7854
+ [:error, :unexpected_token, { :token => 'tRBRACK' }],
7855
+ %q{def foo(...) bar[...]; end},
7856
+ %q{ ^ location},
7857
+ SINCE_2_7)
7858
+
7859
+ assert_diagnoses(
7860
+ [:error, :unexpected_token, { :token => 'tRBRACK' }],
7861
+ %q{def foo(...) bar[...] = x; end},
7862
+ %q{ ^ location},
7863
+ SINCE_2_7)
7864
+
7865
+ assert_diagnoses(
7866
+ [:error, :unexpected_token, { :token => 'tRPAREN' }],
7867
+ %q{def foo(...) defined?(...); end},
7868
+ %q{ ^ location},
7869
+ SINCE_2_7)
7870
+
7871
+ assert_diagnoses(
7872
+ [:error, :unexpected_token, { :token => 'tDOT3' }],
7873
+ %q{def foo ...; end},
7874
+ %q{ ^^^ location},
7875
+ SINCE_2_7)
7876
+ end
7877
+
7878
+ def test_erange_without_parentheses_at_eol
7879
+ assert_diagnoses(
7880
+ [:warning, :triple_dot_at_eol],
7881
+ %Q{1...\n2},
7882
+ %q{ ^^^ location},
7883
+ SINCE_2_7)
7884
+
7885
+ refute_diagnoses('(1...)', SINCE_2_7)
7886
+ refute_diagnoses("(1...\n)", SINCE_2_7)
7887
+ refute_diagnoses("[1...\n]", SINCE_2_7)
7888
+ refute_diagnoses("{a: 1...\n2}", SINCE_2_7)
7889
+ end
7890
+
7891
+ def test_embedded_document_with_eof
7892
+ refute_diagnoses("=begin\n""=end", SINCE_2_7)
7893
+ refute_diagnoses("=begin\n""=end\0", SINCE_2_7)
7894
+ refute_diagnoses("=begin\n""=end\C-d", SINCE_2_7)
7895
+ refute_diagnoses("=begin\n""=end\C-z", SINCE_2_7)
7896
+
7897
+ assert_diagnoses(
7898
+ [:fatal, :embedded_document],
7899
+ "=begin\n",
7900
+ %q{},
7901
+ SINCE_2_7)
7902
+
7903
+ assert_diagnoses(
7904
+ [:fatal, :embedded_document],
7905
+ "=begin",
7906
+ %q{},
7907
+ SINCE_2_7)
7908
+ end
7909
+
7910
+ def test_interp_digit_var
7911
+ # '#@1'
7912
+ assert_parses(
7913
+ s(:str, '#@1'),
7914
+ %q{ '#@1' },
7915
+ %q{},
7916
+ ALL_VERSIONS)
7917
+
7918
+ assert_parses(
7919
+ s(:str, '#@@1'),
7920
+ %q{ '#@@1' },
7921
+ %q{},
7922
+ ALL_VERSIONS)
7923
+
7924
+ # <<-'HERE'
7925
+ # #@1
7926
+ # HERE
7927
+ assert_parses(
7928
+ s(:str, '#@1' + "\n"),
7929
+ %q{<<-'HERE'!#@1!HERE}.gsub('!', "\n"),
7930
+ %q{},
7931
+ ALL_VERSIONS)
7932
+
7933
+ assert_parses(
7934
+ s(:str, '#@@1' + "\n"),
7935
+ %q{<<-'HERE'!#@@1!HERE}.gsub('!', "\n"),
7936
+ %q{},
7937
+ ALL_VERSIONS)
7938
+
7939
+ # %q{#@1}
7940
+ assert_parses(
7941
+ s(:str, '#@1'),
7942
+ %q{ %q{#@1} },
7943
+ %q{},
7944
+ ALL_VERSIONS)
7945
+
7946
+ assert_parses(
7947
+ s(:str, '#@@1'),
7948
+ %q{ %q{#@@1} },
7949
+ %q{},
7950
+ ALL_VERSIONS)
7951
+
7952
+ # "#@1"
7953
+ assert_diagnoses(
7954
+ [:error, :ivar_name, { :name => '@1' }],
7955
+ %q{ "#@1" },
7956
+ %q{ ^^ location},
7957
+ ALL_VERSIONS - SINCE_2_7)
7958
+
7959
+ assert_diagnoses(
7960
+ [:error, :cvar_name, { :name => '@@1' }],
7961
+ %q{ "#@@1" },
7962
+ %q{ ^^^ location},
7963
+ ALL_VERSIONS - SINCE_2_7)
7964
+
7965
+ assert_parses(
7966
+ s(:str, '#@1'),
7967
+ %q{ "#@1" },
7968
+ %q{},
7969
+ SINCE_2_7)
7970
+
7971
+ assert_parses(
7972
+ s(:str, '#@@1'),
7973
+ %q{ "#@@1" },
7974
+ %q{},
7975
+ SINCE_2_7)
7976
+
7977
+ # <<-"HERE"
7978
+ # #@1
7979
+ # HERE
7980
+ assert_diagnoses(
7981
+ [:error, :ivar_name, { :name => '@1' }],
7982
+ %q{ <<-"HERE"!#@1!HERE }.gsub('!', "\n"),
7983
+ %q{ ^^ location},
7984
+ ALL_VERSIONS - SINCE_2_7)
7985
+
7986
+ assert_diagnoses(
7987
+ [:error, :cvar_name, { :name => '@@1' }],
7988
+ %q{ <<-"HERE"!#@@1!HERE }.gsub('!', "\n"),
7989
+ %q{ ^^^ location},
7990
+ ALL_VERSIONS - SINCE_2_7)
7991
+
7992
+ assert_parses(
7993
+ s(:str, '#@1' + "\n"),
7994
+ %q{<<-"HERE"!#@1!HERE}.gsub('!', "\n"),
7995
+ %q{},
7996
+ SINCE_2_7)
7997
+
7998
+ assert_parses(
7999
+ s(:str, '#@@1' + "\n"),
8000
+ %q{<<-"HERE"!#@@1!HERE}.gsub('!', "\n"),
8001
+ %q{},
8002
+ SINCE_2_7)
8003
+
8004
+ # %{#@1}
8005
+ assert_diagnoses(
8006
+ [:error, :ivar_name, { :name => '@1' }],
8007
+ %q{ %{#@1} },
8008
+ %q{ ^^ location},
8009
+ ALL_VERSIONS - SINCE_2_7)
8010
+
8011
+ assert_diagnoses(
8012
+ [:error, :cvar_name, { :name => '@@1' }],
8013
+ %q{ %{#@@1} },
8014
+ %q{ ^^^ location},
8015
+ ALL_VERSIONS - SINCE_2_7)
8016
+
8017
+ assert_parses(
8018
+ s(:str, '#@1'),
8019
+ %q{ %{#@1} },
8020
+ %q{},
8021
+ SINCE_2_7)
8022
+
8023
+ assert_parses(
8024
+ s(:str, '#@@1'),
8025
+ %q{ %{#@@1} },
8026
+ %q{},
8027
+ SINCE_2_7)
8028
+
8029
+ # %Q{#@1}
8030
+ assert_diagnoses(
8031
+ [:error, :ivar_name, { :name => '@1' }],
8032
+ %q{ %Q{#@1} },
8033
+ %q{ ^^ location},
8034
+ ALL_VERSIONS - SINCE_2_7)
8035
+
8036
+ assert_diagnoses(
8037
+ [:error, :cvar_name, { :name => '@@1' }],
8038
+ %q{ %Q{#@@1} },
8039
+ %q{ ^^^ location},
8040
+ ALL_VERSIONS - SINCE_2_7)
8041
+
8042
+ assert_parses(
8043
+ s(:str, '#@1'),
8044
+ %q{ %Q{#@1} },
8045
+ %q{},
8046
+ SINCE_2_7)
8047
+
8048
+ assert_parses(
8049
+ s(:str, '#@@1'),
8050
+ %q{ %Q{#@@1} },
8051
+ %q{},
8052
+ SINCE_2_7)
8053
+
8054
+ # %w[#@1]
8055
+ assert_parses(
8056
+ s(:array,
8057
+ s(:str, '#@1')),
8058
+ %q{ %w[ #@1 ] },
8059
+ %q{},
8060
+ ALL_VERSIONS)
8061
+
8062
+ assert_parses(
8063
+ s(:array,
8064
+ s(:str, '#@@1')),
8065
+ %q{ %w[ #@@1 ] },
8066
+ %q{},
8067
+ ALL_VERSIONS)
8068
+
8069
+ # %W[#@1]
8070
+ assert_diagnoses(
8071
+ [:error, :ivar_name, { :name => '@1' }],
8072
+ %q{ %W[#@1] },
8073
+ %q{ ^^ location},
8074
+ ALL_VERSIONS - SINCE_2_7)
8075
+
8076
+ assert_diagnoses(
8077
+ [:error, :cvar_name, { :name => '@@1' }],
8078
+ %q{ %W[#@@1] },
8079
+ %q{ ^^^ location},
8080
+ ALL_VERSIONS - SINCE_2_7)
8081
+
8082
+ assert_parses(
8083
+ s(:array,
8084
+ s(:str, '#@1')),
8085
+ %q{ %W[#@1] },
8086
+ %q{},
8087
+ SINCE_2_7)
8088
+
8089
+ assert_parses(
8090
+ s(:array,
8091
+ s(:str, '#@@1')),
8092
+ %q{ %W[#@@1] },
8093
+ %q{},
8094
+ SINCE_2_7)
8095
+
8096
+ # %i[#@1]
8097
+ assert_parses(
8098
+ s(:array,
8099
+ s(:sym, :'#@1')),
8100
+ %q{ %i[ #@1 ] },
8101
+ %q{},
8102
+ SINCE_2_0)
8103
+
8104
+ assert_parses(
8105
+ s(:array,
8106
+ s(:sym, :'#@@1')),
8107
+ %q{ %i[ #@@1 ] },
8108
+ %q{},
8109
+ SINCE_2_0)
8110
+
8111
+ # %I[#@1]
8112
+ assert_diagnoses(
8113
+ [:error, :ivar_name, { :name => '@1' }],
8114
+ %q{ %I[#@1] },
8115
+ %q{ ^^ location},
8116
+ SINCE_2_0 - SINCE_2_7)
8117
+
8118
+ assert_diagnoses(
8119
+ [:error, :cvar_name, { :name => '@@1' }],
8120
+ %q{ %I[#@@1] },
8121
+ %q{ ^^^ location},
8122
+ SINCE_2_0 - SINCE_2_7)
8123
+
8124
+ assert_parses(
8125
+ s(:array,
8126
+ s(:sym, :'#@1')),
8127
+ %q{ %I[#@1] },
8128
+ %q{},
8129
+ SINCE_2_7)
8130
+
8131
+ assert_parses(
8132
+ s(:array,
8133
+ s(:sym, :'#@@1')),
8134
+ %q{ %I[#@@1] },
8135
+ %q{},
8136
+ SINCE_2_7)
8137
+
8138
+ # :'#@1'
8139
+ assert_parses(
8140
+ s(:sym, :'#@1'),
8141
+ %q{ :'#@1' },
8142
+ %q{},
8143
+ ALL_VERSIONS)
8144
+
8145
+ assert_parses(
8146
+ s(:sym, :'#@@1'),
8147
+ %q{ :'#@@1' },
8148
+ %q{},
8149
+ ALL_VERSIONS)
8150
+
8151
+ # %s{#@1}
8152
+ assert_parses(
8153
+ s(:sym, :'#@1'),
8154
+ %q{ %s{#@1} },
8155
+ %q{},
8156
+ ALL_VERSIONS)
8157
+
8158
+ assert_parses(
8159
+ s(:sym, :'#@@1'),
8160
+ %q{ %s{#@@1} },
8161
+ %q{},
8162
+ ALL_VERSIONS)
8163
+
8164
+ # :"#@1"
8165
+ assert_diagnoses(
8166
+ [:error, :ivar_name, { :name => '@1' }],
8167
+ %q{ :"#@1" },
8168
+ %q{ ^^ location},
8169
+ ALL_VERSIONS - SINCE_2_7)
8170
+
8171
+ assert_diagnoses(
8172
+ [:error, :cvar_name, { :name => '@@1' }],
8173
+ %q{ :"#@@1" },
8174
+ %q{ ^^^ location},
8175
+ ALL_VERSIONS - SINCE_2_7)
8176
+
8177
+ assert_parses(
8178
+ s(:sym, :'#@1'),
8179
+ %q{ :"#@1" },
8180
+ %q{},
8181
+ SINCE_2_7)
8182
+
8183
+ assert_parses(
8184
+ s(:sym, :'#@@1'),
8185
+ %q{ :"#@@1" },
8186
+ %q{},
8187
+ SINCE_2_7)
8188
+
8189
+ # /#@1/
8190
+ assert_diagnoses(
8191
+ [:error, :ivar_name, { :name => '@1' }],
8192
+ %q{ /#@1/ },
8193
+ %q{ ^^ location},
8194
+ ALL_VERSIONS - SINCE_2_7)
8195
+
8196
+ assert_diagnoses(
8197
+ [:error, :cvar_name, { :name => '@@1' }],
8198
+ %q{ /#@@1/ },
8199
+ %q{ ^^^ location},
8200
+ ALL_VERSIONS - SINCE_2_7)
8201
+
8202
+ assert_parses(
8203
+ s(:regexp,
8204
+ s(:str, '#@1'),
8205
+ s(:regopt)),
8206
+ %q{ /#@1/ },
8207
+ %q{},
8208
+ SINCE_2_7)
8209
+
8210
+ assert_parses(
8211
+ s(:regexp,
8212
+ s(:str, '#@@1'),
8213
+ s(:regopt)),
8214
+ %q{ /#@@1/ },
8215
+ %q{},
8216
+ SINCE_2_7)
8217
+
8218
+ # %r{#@1}
8219
+ assert_diagnoses(
8220
+ [:error, :ivar_name, { :name => '@1' }],
8221
+ %q{ %r{#@1} },
8222
+ %q{ ^^ location},
8223
+ ALL_VERSIONS - SINCE_2_7)
8224
+
8225
+ assert_diagnoses(
8226
+ [:error, :cvar_name, { :name => '@@1' }],
8227
+ %q{ %r{#@@1} },
8228
+ %q{ ^^^ location},
8229
+ ALL_VERSIONS - SINCE_2_7)
8230
+
8231
+ assert_parses(
8232
+ s(:regexp,
8233
+ s(:str, '#@1'),
8234
+ s(:regopt)),
8235
+ %q{ %r{#@1} },
8236
+ %q{},
8237
+ SINCE_2_7)
8238
+
8239
+ assert_parses(
8240
+ s(:regexp,
8241
+ s(:str, '#@@1'),
8242
+ s(:regopt)),
8243
+ %q{ %r{#@@1} },
8244
+ %q{},
8245
+ SINCE_2_7)
8246
+
8247
+ # %x{#@1}
8248
+ assert_diagnoses(
8249
+ [:error, :ivar_name, { :name => '@1' }],
8250
+ %q{ %x{#@1} },
8251
+ %q{ ^^ location},
8252
+ ALL_VERSIONS - SINCE_2_7)
8253
+
8254
+ assert_diagnoses(
8255
+ [:error, :cvar_name, { :name => '@@1' }],
8256
+ %q{ %x{#@@1} },
8257
+ %q{ ^^^ location},
8258
+ ALL_VERSIONS - SINCE_2_7)
8259
+
8260
+ assert_parses(
8261
+ s(:xstr,
8262
+ s(:str, '#@1')),
8263
+ %q{ %x{#@1} },
8264
+ %q{},
8265
+ SINCE_2_7)
8266
+
8267
+ assert_parses(
8268
+ s(:xstr,
8269
+ s(:str, '#@@1')),
8270
+ %q{ %x{#@@1} },
8271
+ %q{},
8272
+ SINCE_2_7)
8273
+
8274
+ # `#@1`
8275
+ assert_diagnoses(
8276
+ [:error, :ivar_name, { :name => '@1' }],
8277
+ %q{ `#@1` },
8278
+ %q{ ^^ location},
8279
+ ALL_VERSIONS - SINCE_2_7)
8280
+
8281
+ assert_diagnoses(
8282
+ [:error, :cvar_name, { :name => '@@1' }],
8283
+ %q{ `#@@1` },
8284
+ %q{ ^^^ location},
8285
+ ALL_VERSIONS - SINCE_2_7)
8286
+
8287
+ assert_parses(
8288
+ s(:xstr,
8289
+ s(:str, '#@1')),
8290
+ %q{ `#@1` },
8291
+ %q{},
8292
+ SINCE_2_7)
8293
+
8294
+ assert_parses(
8295
+ s(:xstr,
8296
+ s(:str, '#@@1')),
8297
+ %q{ `#@@1` },
8298
+ %q{},
8299
+ SINCE_2_7)
8300
+
8301
+ # <<-`HERE`
8302
+ # #@1
8303
+ # HERE
8304
+ assert_diagnoses(
8305
+ [:error, :ivar_name, { :name => '@1' }],
8306
+ %q{ <<-`HERE`!#@1!HERE }.gsub('!', "\n"),
8307
+ %q{ ^^ location},
8308
+ ALL_VERSIONS - SINCE_2_7)
8309
+
8310
+ assert_diagnoses(
8311
+ [:error, :cvar_name, { :name => '@@1' }],
8312
+ %q{ <<-`HERE`!#@@1!HERE }.gsub('!', "\n"),
8313
+ %q{ ^^^ location},
8314
+ ALL_VERSIONS - SINCE_2_7)
8315
+
8316
+ assert_parses(
8317
+ s(:xstr,
8318
+ s(:str, '#@1' + "\n")),
8319
+ %q{<<-`HERE`!#@1!HERE}.gsub('!', "\n"),
8320
+ %q{},
8321
+ SINCE_2_7)
8322
+
8323
+ assert_parses(
8324
+ s(:xstr,
8325
+ s(:str, '#@@1' + "\n")),
8326
+ %q{<<-`HERE`!#@@1!HERE}.gsub('!', "\n"),
8327
+ %q{},
8328
+ SINCE_2_7)
8329
+ end
8330
+
8331
+ def assert_parses_pattern_match(ast, code, source_maps = '', versions = SINCE_2_7)
8332
+ case_pre = "case foo; "
8333
+ source_maps_offset = case_pre.length
8334
+ source_maps_prefix = ' ' * source_maps_offset
8335
+ source_maps = source_maps
8336
+ .lines
8337
+ .map { |line| source_maps_prefix + line.sub(/^\s*\|/, '') }
8338
+ .join("\n")
8339
+
8340
+ assert_parses(
8341
+ s(:case_match,
8342
+ s(:lvar, :foo),
8343
+ ast,
8344
+ nil),
8345
+ "#{case_pre}#{code}; end",
8346
+ source_maps,
8347
+ SINCE_2_7
8348
+ )
8349
+ end
8350
+
8351
+ def test_pattern_matching_single_match
8352
+ assert_parses_pattern_match(
8353
+ s(:in_pattern,
8354
+ s(:match_var, :x),
8355
+ nil,
8356
+ s(:lvar, :x)),
8357
+ %q{in x then x},
8358
+ %q{~~ keyword (in_pattern)
8359
+ |~~~~~~~~~~~ expression (in_pattern)
8360
+ | ~~~~ begin (in_pattern)
8361
+ | ~ expression (in_pattern.match_var)
8362
+ | ~ name (in_pattern.match_var)}
8363
+ )
8364
+ end
8365
+
8366
+ def test_pattern_matching_no_body
8367
+ assert_parses_pattern_match(
8368
+ s(:in_pattern,
8369
+ s(:int, 1), nil, nil),
8370
+ %q{in 1}
8371
+ )
8372
+ end
8373
+
8374
+ def test_pattern_matching_if_unless_modifiers
8375
+ assert_parses_pattern_match(
8376
+ s(:in_pattern,
8377
+ s(:match_var, :x),
8378
+ s(:if_guard, s(:true)),
8379
+ s(:nil)
8380
+ ),
8381
+ %q{in x if true; nil},
8382
+ %q{~~ keyword (in_pattern)
8383
+ |~~~~~~~~~~~~~~~~~ expression (in_pattern)
8384
+ | ~ begin (in_pattern)
8385
+ | ~~ keyword (in_pattern.if_guard)
8386
+ | ~~~~~~~ expression (in_pattern.if_guard)}
8387
+ )
8388
+
8389
+ assert_parses_pattern_match(
8390
+ s(:in_pattern,
8391
+ s(:match_var, :x),
8392
+ s(:unless_guard, s(:true)),
8393
+ s(:nil)
8394
+ ),
8395
+ %q{in x unless true; nil},
8396
+ %q{~~ keyword (in_pattern)
8397
+ |~~~~~~~~~~~~~~~~~~~~~ expression (in_pattern)
8398
+ | ~ begin (in_pattern)
8399
+ | ~~~~~~ keyword (in_pattern.unless_guard)
8400
+ | ~~~~~~~~~~~ expression (in_pattern.unless_guard)}
8401
+ )
8402
+ end
8403
+
8404
+ def test_pattern_matching_pin_variable
8405
+ assert_parses_pattern_match(
8406
+ s(:in_pattern,
8407
+ s(:pin, s(:lvar, :foo)),
8408
+ nil,
8409
+ s(:nil)),
8410
+ %q{in ^foo then nil},
8411
+ %q{ ~ selector (in_pattern.pin)
8412
+ | ~~~~ expression (in_pattern.pin)
8413
+ | ~~~ name (in_pattern.pin.lvar)}
8414
+ )
8415
+ end
8416
+
8417
+ def test_pattern_matching_implicit_array_match
8418
+ assert_parses_pattern_match(
8419
+ s(:in_pattern,
8420
+ s(:array_pattern_with_tail,
8421
+ s(:match_var, :x)),
8422
+ nil,
8423
+ s(:nil)),
8424
+ %q{in x, then nil},
8425
+ %q{ ~ expression (in_pattern.array_pattern_with_tail)}
8426
+ )
8427
+
8428
+ assert_parses_pattern_match(
8429
+ s(:in_pattern,
8430
+ s(:array_pattern,
8431
+ s(:match_rest,
8432
+ s(:match_var, :x))),
8433
+ nil,
8434
+ s(:nil)),
8435
+ %q{in *x then nil},
8436
+ %q{ ~~ expression (in_pattern.array_pattern)
8437
+ | ~ operator (in_pattern.array_pattern.match_rest)
8438
+ | ~ name (in_pattern.array_pattern.match_rest.match_var)}
8439
+ )
8440
+
8441
+ assert_parses_pattern_match(
8442
+ s(:in_pattern,
8443
+ s(:array_pattern,
8444
+ s(:match_rest)),
8445
+ nil,
8446
+ s(:nil)),
8447
+ %q{in * then nil},
8448
+ %q{ ~ expression (in_pattern.array_pattern)
8449
+ | ~ operator (in_pattern.array_pattern.match_rest)}
8450
+ )
8451
+
8452
+ assert_parses_pattern_match(
8453
+ s(:in_pattern,
8454
+ s(:array_pattern,
8455
+ s(:match_var, :x),
8456
+ s(:match_var, :y)),
8457
+ nil,
8458
+ s(:nil)),
8459
+ %q{in x, y then nil},
8460
+ %q{ ~~~~ expression (in_pattern.array_pattern)}
8461
+ )
8462
+
8463
+ assert_parses_pattern_match(
8464
+ s(:in_pattern,
8465
+ s(:array_pattern_with_tail,
8466
+ s(:match_var, :x),
8467
+ s(:match_var, :y)),
8468
+ nil,
8469
+ s(:nil)),
8470
+ %q{in x, y, then nil},
8471
+ %q{ ~~~~ expression (in_pattern.array_pattern_with_tail)}
8472
+ )
8473
+
8474
+ assert_parses_pattern_match(
8475
+ s(:in_pattern,
8476
+ s(:array_pattern,
8477
+ s(:match_var, :x),
8478
+ s(:match_rest, s(:match_var, :y)),
8479
+ s(:match_var, :z)),
8480
+ nil,
8481
+ s(:nil)),
8482
+ %q{in x, *y, z then nil},
8483
+ %q{ ~~~~~~~~ expression (in_pattern.array_pattern)}
8484
+ )
8485
+
8486
+ assert_parses_pattern_match(
8487
+ s(:in_pattern,
8488
+ s(:array_pattern,
8489
+ s(:match_rest, s(:match_var, :x)),
8490
+ s(:match_var, :y),
8491
+ s(:match_var, :z)),
8492
+ nil,
8493
+ s(:nil)),
8494
+ %q{in *x, y, z then nil},
8495
+ %q{ ~~~~~~~~ expression (in_pattern.array_pattern)}
8496
+ )
8497
+
8498
+ assert_parses_pattern_match(
8499
+ s(:in_pattern,
8500
+ s(:array_pattern,
8501
+ s(:int, 1),
8502
+ s(:str, 'a'),
8503
+ s(:array_pattern),
8504
+ s(:hash_pattern)),
8505
+ nil,
8506
+ s(:nil)),
8507
+ %q{in 1, "a", [], {} then nil},
8508
+ %q{ ~~~~~~~~~~~~~~ expression (in_pattern.array_pattern)}
8509
+ )
8510
+ end
8511
+
8512
+ def test_pattern_matching_explicit_array_match
8513
+ assert_parses_pattern_match(
8514
+ s(:in_pattern,
8515
+ s(:array_pattern,
8516
+ s(:match_var, :x)),
8517
+ nil,
8518
+ s(:nil)),
8519
+ %q{in [x] then nil},
8520
+ %q{ ~~~ expression (in_pattern.array_pattern)
8521
+ | ~ begin (in_pattern.array_pattern)
8522
+ | ~ end (in_pattern.array_pattern)}
8523
+ )
8524
+
8525
+ assert_parses_pattern_match(
8526
+ s(:in_pattern,
8527
+ s(:array_pattern_with_tail,
8528
+ s(:match_var, :x)),
8529
+ nil,
8530
+ s(:nil)),
8531
+ %q{in [x,] then nil},
8532
+ %q{ ~~~~ expression (in_pattern.array_pattern_with_tail)
8533
+ | ~ begin (in_pattern.array_pattern_with_tail)
8534
+ | ~ end (in_pattern.array_pattern_with_tail)}
8535
+ )
8536
+
8537
+ assert_parses_pattern_match(
8538
+ s(:in_pattern,
8539
+ s(:array_pattern,
8540
+ s(:match_var, :x),
8541
+ s(:match_var, :y)),
8542
+ nil,
8543
+ s(:true)),
8544
+ %q{in [x, y] then true},
8545
+ %q{ ~~~~~~ expression (in_pattern.array_pattern)
8546
+ | ~ begin (in_pattern.array_pattern)
8547
+ | ~ end (in_pattern.array_pattern)}
8548
+ )
8549
+
8550
+ assert_parses_pattern_match(
8551
+ s(:in_pattern,
8552
+ s(:array_pattern_with_tail,
8553
+ s(:match_var, :x),
8554
+ s(:match_var, :y)),
8555
+ nil,
8556
+ s(:true)),
8557
+ %q{in [x, y,] then true},
8558
+ %q{ ~~~~~~~ expression (in_pattern.array_pattern_with_tail)
8559
+ | ~ begin (in_pattern.array_pattern_with_tail)
8560
+ | ~ end (in_pattern.array_pattern_with_tail)}
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)),
8569
+ nil,
8570
+ s(:true)),
8571
+ %q{in [x, y, *] 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_var, :y),
8582
+ s(:match_rest, 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, s(:match_var, :y)),
8596
+ s(:match_var, :z)),
8597
+ nil,
8598
+ s(:true)),
8599
+ %q{in [x, *y, z] 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_var, :x),
8609
+ s(:match_rest),
8610
+ s(:match_var, :y)),
8611
+ nil,
8612
+ s(:true)),
8613
+ %q{in [x, *, y] then true},
8614
+ %q{ ~~~~~~~~~ expression (in_pattern.array_pattern)
8615
+ | ~ begin (in_pattern.array_pattern)
8616
+ | ~ end (in_pattern.array_pattern)}
8617
+ )
8618
+
8619
+ assert_parses_pattern_match(
8620
+ s(:in_pattern,
8621
+ s(:array_pattern,
8622
+ s(:match_rest, s(:match_var, :x)),
8623
+ s(:match_var, :y)),
8624
+ nil,
8625
+ s(:true)),
8626
+ %q{in [*x, y] then true},
8627
+ %q{ ~~~~~~~ expression (in_pattern.array_pattern)
8628
+ | ~ begin (in_pattern.array_pattern)
8629
+ | ~ end (in_pattern.array_pattern)}
8630
+ )
8631
+
8632
+ assert_parses_pattern_match(
8633
+ s(:in_pattern,
8634
+ s(:array_pattern,
8635
+ s(:match_rest),
8636
+ s(:match_var, :x)),
8637
+ nil,
8638
+ s(:true)),
8639
+ %q{in [*, x] then true},
8640
+ %q{ ~~~~~~ expression (in_pattern.array_pattern)
8641
+ | ~ begin (in_pattern.array_pattern)
8642
+ | ~ end (in_pattern.array_pattern)}
8643
+ )
8644
+ end
8645
+
8646
+ def test_pattern_matching_hash
8647
+ assert_parses_pattern_match(
8648
+ s(:in_pattern,
8649
+ s(:hash_pattern),
8650
+ nil,
8651
+ s(:true)),
8652
+ %q{in {} then true},
8653
+ %q{ ~~ expression (in_pattern.hash_pattern)}
8654
+ )
8655
+
8656
+ assert_parses_pattern_match(
8657
+ s(:in_pattern,
8658
+ s(:hash_pattern,
8659
+ s(:pair, s(:sym, :a), s(:int, 1))),
8660
+ nil,
8661
+ s(:true)),
8662
+ %q{in a: 1 then true},
8663
+ %q{ ~~~~ expression (in_pattern.hash_pattern)}
8664
+ )
8665
+
8666
+ assert_parses_pattern_match(
8667
+ s(:in_pattern,
8668
+ s(:hash_pattern,
8669
+ s(:pair, s(:sym, :a), s(:int, 1))),
8670
+ nil,
8671
+ s(:true)),
8672
+ %q{in { a: 1 } then true},
8673
+ %q{ ~~~~~~~~ expression (in_pattern.hash_pattern)
8674
+ | ~ begin (in_pattern.hash_pattern)
8675
+ | ~ end (in_pattern.hash_pattern)}
8676
+ )
8677
+
8678
+ assert_parses_pattern_match(
8679
+ s(:in_pattern,
8680
+ s(:hash_pattern,
8681
+ s(:match_var, :a)),
8682
+ nil,
8683
+ s(:true)),
8684
+ %q{in a: then true},
8685
+ %q{ ~~ expression (in_pattern.hash_pattern)
8686
+ | ~ name (in_pattern.hash_pattern.match_var)
8687
+ | ~~ expression (in_pattern.hash_pattern.match_var)}
8688
+ )
8689
+
8690
+ assert_parses_pattern_match(
8691
+ s(:in_pattern,
8692
+ s(:hash_pattern,
8693
+ s(:match_rest, s(:match_var, :a))),
8694
+ nil,
8695
+ s(:true)),
8696
+ %q{in **a 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
+ | ~ expression (in_pattern.hash_pattern.match_rest.match_var)
8701
+ | ~ name (in_pattern.hash_pattern.match_rest.match_var)}
8702
+ )
8703
+
8704
+ assert_parses_pattern_match(
8705
+ s(:in_pattern,
8706
+ s(:hash_pattern,
8707
+ s(:match_rest)),
8708
+ nil,
8709
+ s(:true)),
8710
+ %q{in ** then true},
8711
+ %q{ ~~ expression (in_pattern.hash_pattern)
8712
+ | ~~ expression (in_pattern.hash_pattern.match_rest)
8713
+ | ~~ operator (in_pattern.hash_pattern.match_rest)}
8714
+ )
8715
+
8716
+ assert_parses_pattern_match(
8717
+ s(:in_pattern,
8718
+ s(:hash_pattern,
8719
+ s(:pair, s(:sym, :a), s(:int, 1)),
8720
+ s(:pair, s(:sym, :b), s(:int, 2))),
8721
+ nil,
8722
+ s(:true)),
8723
+ %q{in a: 1, b: 2 then true},
8724
+ %q{ ~~~~~~~~~~ expression (in_pattern.hash_pattern)}
8725
+ )
8726
+
8727
+ assert_parses_pattern_match(
8728
+ s(:in_pattern,
8729
+ s(:hash_pattern,
8730
+ s(:match_var, :a),
8731
+ s(:match_var, :b)),
8732
+ nil,
8733
+ s(:true)),
8734
+ %q{in a:, b: then true},
8735
+ %q{ ~~~~~~ expression (in_pattern.hash_pattern)}
8736
+ )
8737
+
8738
+ assert_parses_pattern_match(
8739
+ s(:in_pattern,
8740
+ s(:hash_pattern,
8741
+ s(:pair, s(:sym, :a), s(:int, 1)),
8742
+ s(:match_var, :_a),
8743
+ s(:match_rest)),
8744
+ nil,
8745
+ s(:true)),
8746
+ %q{in a: 1, _a:, ** then true},
8747
+ %q{ ~~~~~~~~~~~~~ expression (in_pattern.hash_pattern)}
8748
+ )
8749
+ end
8750
+
8751
+ def test_pattern_matching_hash_with_string_keys
8752
+ # Match + assign
8753
+
8754
+ assert_parses_pattern_match(
8755
+ s(:in_pattern,
8756
+ s(:hash_pattern,
8757
+ s(:match_var, :a)),
8758
+ nil,
8759
+ s(:true)),
8760
+ %q{in "a": then true},
8761
+ %q{ ~~~~ expression (in_pattern.hash_pattern.match_var)
8762
+ | ~ name (in_pattern.hash_pattern.match_var)}
8763
+ )
8764
+
8765
+ assert_parses_pattern_match(
8766
+ s(:in_pattern,
8767
+ s(:hash_pattern,
8768
+ s(:match_var, :a)),
8769
+ nil,
8770
+ s(:true)),
8771
+ %q{in "#{ 'a' }": then true},
8772
+ %q{ ~~~~~~~~~~~ expression (in_pattern.hash_pattern.match_var)
8773
+ | ~ name (in_pattern.hash_pattern.match_var)}
8774
+ )
8775
+
8776
+ assert_parses_pattern_match(
8777
+ s(:in_pattern,
8778
+ s(:hash_pattern,
8779
+ s(:match_var, :a)),
8780
+ nil,
8781
+ s(:true)),
8782
+ %q{in "#{ %q{a} }": then true},
8783
+ %q{ ~~~~~~~~~~~~~ expression (in_pattern.hash_pattern.match_var)
8784
+ | ~ name (in_pattern.hash_pattern.match_var)}
8785
+ )
8786
+
8787
+ assert_parses_pattern_match(
8788
+ s(:in_pattern,
8789
+ s(:hash_pattern,
8790
+ s(:match_var, :a)),
8791
+ nil,
8792
+ s(:true)),
8793
+ %q{in "#{ %Q{a} }": then true},
8794
+ %q{ ~~~~~~~~~~~~~ expression (in_pattern.hash_pattern.match_var)
8795
+ | ~ name (in_pattern.hash_pattern.match_var)}
8796
+ )
8797
+
8798
+ # Only match
8799
+
8800
+ assert_parses_pattern_match(
8801
+ s(:in_pattern,
8802
+ s(:hash_pattern,
8803
+ s(:pair, s(:sym, :a), s(:int, 1))),
8804
+ nil,
8805
+ s(:true)),
8806
+ %q{in "a": 1 then true},
8807
+ )
8808
+
8809
+ assert_parses_pattern_match(
8810
+ s(:in_pattern,
8811
+ s(:hash_pattern,
8812
+ s(:pair,
8813
+ s(:dsym, s(:begin, s(:str, "a"))),
8814
+ s(:int, 1))),
8815
+ nil,
8816
+ s(:true)),
8817
+ %q{in "#{ 'a' }": 1 then true},
8818
+ )
8819
+
8820
+ assert_parses_pattern_match(
8821
+ s(:in_pattern,
8822
+ s(:hash_pattern,
8823
+ s(:pair,
8824
+ s(:dsym, s(:begin, s(:str, "a"))),
8825
+ s(:int, 1))),
8826
+ nil,
8827
+ s(:true)),
8828
+ %q{in "#{ %q{a} }": 1 then true},
8829
+ )
8830
+
8831
+ assert_parses_pattern_match(
8832
+ s(:in_pattern,
8833
+ s(:hash_pattern,
8834
+ s(:pair,
8835
+ s(:dsym, s(:begin, s(:str, "a"))),
8836
+ s(:int, 1))),
8837
+ nil,
8838
+ s(:true)),
8839
+ %q{in "#{ %Q{a} }": 1 then true},
8840
+ )
8841
+ end
8842
+
8843
+ def test_pattern_matching_hash_with_heredoc_keys
8844
+ # Ruby <3, the following case is acceptable by the MRI's grammar,
8845
+ # so it has to be reducable by parser.
8846
+ # We have a code for that in the builder.rb that reject it via
8847
+ # diagnostic error because of the wrong lvar name
8848
+ assert_diagnoses(
8849
+ [:error, :lvar_name, { name: "a\n" }],
8850
+ %Q{case nil; in "\#{ <<-HERE }":;\na\nHERE\nelse\nend},
8851
+ %q{ ~~~~~~~ location},
8852
+ SINCE_2_7
8853
+ )
8854
+ end
8855
+
8856
+ def test_pattern_matching_hash_with_string_interpolation_keys
8857
+ assert_diagnoses(
8858
+ [:error, :pm_interp_in_var_name],
8859
+ %q{case a; in "#{a}": 1; end},
8860
+ %q{ ~~~~~~~ location},
8861
+ SINCE_2_7
8862
+ )
8863
+ end
8864
+
8865
+ def test_pattern_matching_keyword_variable
8866
+ assert_parses_pattern_match(
8867
+ s(:in_pattern,
8868
+ s(:self),
8869
+ nil,
8870
+ s(:true)),
8871
+ %q{in self then true}
8872
+ )
8873
+ end
8874
+
8875
+ def test_pattern_matching_lambda
8876
+ assert_parses_pattern_match(
8877
+ s(:in_pattern,
8878
+ s(:block,
8879
+ s(:lambda),
8880
+ s(:args),
8881
+ s(:int, 42)),
8882
+ nil,
8883
+ s(:true)),
8884
+ %q{in ->{ 42 } then true}
8885
+ )
8886
+ end
8887
+
8888
+ def test_pattern_matching_ranges
8889
+ assert_parses_pattern_match(
8890
+ s(:in_pattern,
8891
+ s(:irange, s(:int, 1), s(:int, 2)),
8892
+ nil,
8893
+ s(:true)),
8894
+ %q{in 1..2 then true}
8895
+ )
8896
+
8897
+ assert_parses_pattern_match(
8898
+ s(:in_pattern,
8899
+ s(:irange, s(:int, 1), nil),
8900
+ nil,
8901
+ s(:true)),
8902
+ %q{in 1.. then true}
8903
+ )
8904
+
8905
+ assert_parses_pattern_match(
8906
+ s(:in_pattern,
8907
+ s(:irange, nil, s(:int, 2)),
8908
+ nil,
8909
+ s(:true)),
8910
+ %q{in ..2 then true}
8911
+ )
8912
+
8913
+ assert_parses_pattern_match(
8914
+ s(:in_pattern,
8915
+ s(:erange, s(:int, 1), s(:int, 2)),
8916
+ nil,
8917
+ s(:true)),
8918
+ %q{in 1...2 then true}
8919
+ )
8920
+
8921
+ assert_parses_pattern_match(
8922
+ s(:in_pattern,
8923
+ s(:erange, s(:int, 1), nil),
8924
+ nil,
8925
+ s(:true)),
8926
+ %q{in 1... then true}
8927
+ )
8928
+
8929
+ assert_parses_pattern_match(
8930
+ s(:in_pattern,
8931
+ s(:erange, nil, s(:int, 2)),
8932
+ nil,
8933
+ s(:true)),
8934
+ %q{in ...2 then true}
8935
+ )
8936
+ end
8937
+
8938
+ def test_pattern_matching_expr_in_paren
8939
+ assert_parses_pattern_match(
8940
+ s(:in_pattern,
8941
+ s(:begin, s(:int, 1)),
8942
+ nil,
8943
+ s(:true)),
8944
+ %q{in (1) then true},
8945
+ %q{ ~~~ expression (in_pattern.begin)
8946
+ | ~ begin (in_pattern.begin)
8947
+ | ~ end (in_pattern.begin)}
8948
+ )
8949
+ end
8950
+
8951
+ def test_pattern_matching_constants
8952
+ assert_parses_pattern_match(
8953
+ s(:in_pattern,
8954
+ s(:const, nil, :A),
8955
+ nil,
8956
+ s(:true)),
8957
+ %q{in A then true},
8958
+ %q{ ~ expression (in_pattern.const)
8959
+ | ~ name (in_pattern.const)}
8960
+ )
8961
+
8962
+ assert_parses_pattern_match(
8963
+ s(:in_pattern,
8964
+ s(:const, s(:const, nil, :A), :B),
8965
+ nil,
8966
+ s(:true)),
8967
+ %q{in A::B then true},
8968
+ %q{ ~~~~ expression (in_pattern.const)
8969
+ | ~~ double_colon (in_pattern.const)
8970
+ | ~ name (in_pattern.const)}
8971
+ )
8972
+
8973
+ assert_parses_pattern_match(
8974
+ s(:in_pattern,
8975
+ s(:const, s(:cbase), :A),
8976
+ nil,
8977
+ s(:true)),
8978
+ %q{in ::A then true},
8979
+ %q{ ~~~ expression (in_pattern.const)
8980
+ | ~~ double_colon (in_pattern.const)
8981
+ | ~ name (in_pattern.const)}
8982
+ )
8983
+ end
8984
+
8985
+ def test_pattern_matching_const_pattern
8986
+ assert_parses_pattern_match(
8987
+ s(:in_pattern,
8988
+ s(:const_pattern,
8989
+ s(:const, nil, :A),
8990
+ s(:array_pattern,
8991
+ s(:int, 1),
8992
+ s(:int, 2))),
8993
+ nil,
8994
+ s(:true)),
8995
+ %q{in A(1, 2) then true},
8996
+ %q{ ~~~~~~ expression (in_pattern.const_pattern)
8997
+ | ~ begin (in_pattern.const_pattern)
8998
+ | ~ end (in_pattern.const_pattern)
8999
+ | ~ expression (in_pattern.const_pattern.const)
9000
+ | ~~~~ expression (in_pattern.const_pattern.array_pattern)}
9001
+ )
9002
+
9003
+ assert_parses_pattern_match(
9004
+ s(:in_pattern,
9005
+ s(:const_pattern,
9006
+ s(:const, nil, :A),
9007
+ s(:hash_pattern,
9008
+ s(:match_var, :x))),
9009
+ nil,
9010
+ s(:true)),
9011
+ %q{in A(x:) then true},
9012
+ %q{ ~~~~ expression (in_pattern.const_pattern)
9013
+ | ~ begin (in_pattern.const_pattern)
9014
+ | ~ end (in_pattern.const_pattern)
9015
+ | ~ expression (in_pattern.const_pattern.const)
9016
+ | ~~ expression (in_pattern.const_pattern.hash_pattern)}
9017
+ )
9018
+
9019
+ assert_parses_pattern_match(
9020
+ s(:in_pattern,
9021
+ s(:const_pattern,
9022
+ s(:const, nil, :A),
9023
+ s(:array_pattern)),
9024
+ nil,
9025
+ s(:true)),
9026
+ %q{in A() then true},
9027
+ %q{ ~~ expression (in_pattern.const_pattern)
9028
+ | ~ begin (in_pattern.const_pattern)
9029
+ | ~ end (in_pattern.const_pattern)
9030
+ | ~ expression (in_pattern.const_pattern.const)
9031
+ | ~~ expression (in_pattern.const_pattern.array_pattern)}
9032
+ )
9033
+
9034
+ assert_parses_pattern_match(
9035
+ s(:in_pattern,
9036
+ s(:const_pattern,
9037
+ s(:const, nil, :A),
9038
+ s(:array_pattern,
9039
+ s(:int, 1),
9040
+ s(:int, 2))),
9041
+ nil,
9042
+ s(:true)),
9043
+ %q{in A[1, 2] then true},
9044
+ %q{ ~~~~~~ expression (in_pattern.const_pattern)
9045
+ | ~ begin (in_pattern.const_pattern)
9046
+ | ~ end (in_pattern.const_pattern)
9047
+ | ~ expression (in_pattern.const_pattern.const)
9048
+ | ~~~~ expression (in_pattern.const_pattern.array_pattern)}
9049
+ )
9050
+
9051
+ assert_parses_pattern_match(
9052
+ s(:in_pattern,
9053
+ s(:const_pattern,
9054
+ s(:const, nil, :A),
9055
+ s(:hash_pattern,
9056
+ s(:match_var, :x))),
9057
+ nil,
9058
+ s(:true)),
9059
+ %q{in A[x:] then true},
9060
+ %q{ ~~~~ expression (in_pattern.const_pattern)
9061
+ | ~ begin (in_pattern.const_pattern)
9062
+ | ~ end (in_pattern.const_pattern)
9063
+ | ~ expression (in_pattern.const_pattern.const)
9064
+ | ~~ expression (in_pattern.const_pattern.hash_pattern)}
9065
+ )
9066
+
9067
+ assert_parses_pattern_match(
9068
+ s(:in_pattern,
9069
+ s(:const_pattern,
9070
+ s(:const, nil, :A),
9071
+ s(:array_pattern)),
9072
+ nil,
9073
+ s(:true)),
9074
+ %q{in A[] then true},
9075
+ %q{ ~~ expression (in_pattern.const_pattern)
9076
+ | ~ begin (in_pattern.const_pattern)
9077
+ | ~ end (in_pattern.const_pattern)
9078
+ | ~~ expression (in_pattern.const_pattern.array_pattern)}
9079
+ )
9080
+ end
9081
+
9082
+ def test_pattern_matching_match_alt
9083
+ assert_parses_pattern_match(
9084
+ s(:in_pattern,
9085
+ s(:match_alt, s(:int, 1), s(:int, 2)),
9086
+ nil,
9087
+ s(:true)),
9088
+ %q{in 1 | 2 then true},
9089
+ %q{ ~~~~~ expression (in_pattern.match_alt)
9090
+ | ~ operator (in_pattern.match_alt)}
9091
+ )
9092
+ end
9093
+
9094
+ def test_pattern_matching_match_as
9095
+ assert_parses_pattern_match(
9096
+ s(:in_pattern,
9097
+ s(:match_as,
9098
+ s(:int, 1),
9099
+ s(:match_var, :a)),
9100
+ nil,
9101
+ s(:true)),
9102
+ %q{in 1 => a then true},
9103
+ %q{ ~~~~~~ expression (in_pattern.match_as)
9104
+ | ~~ operator (in_pattern.match_as)}
9105
+ )
9106
+ end
9107
+
9108
+ def test_pattern_matching_else
9109
+ assert_parses(
9110
+ s(:case_match,
9111
+ s(:int, 1),
9112
+ s(:in_pattern,
9113
+ s(:int, 2), nil,
9114
+ s(:int, 3)),
9115
+ s(:int, 4)),
9116
+ %q{case 1; in 2; 3; else; 4; end},
9117
+ %q{ ~~~~ else},
9118
+ SINCE_2_7
9119
+ )
9120
+ end
9121
+
9122
+ def test_pattern_matching_blank_else
9123
+ assert_parses(
9124
+ s(:case_match,
9125
+ s(:int, 1),
9126
+ s(:in_pattern,
9127
+ s(:int, 2), nil,
9128
+ s(:int, 3)),
9129
+ s(:empty_else)),
9130
+ %q{case 1; in 2; 3; else; end},
9131
+ %q{ ~~~~ else},
9132
+ SINCE_2_7
9133
+ )
9134
+ end
9135
+
9136
+ def assert_pattern_matching_defines_local_variables(match_code, lvar_names, versions = SINCE_2_7)
9137
+ code = "case 1; #{match_code}; then [#{lvar_names.join(', ')}]; end"
9138
+
9139
+ with_versions(versions) do |version, parser|
9140
+ source_file = Parser::Source::Buffer.new('(assert_context)')
9141
+ source_file.source = code
9142
+
9143
+ lvar_names.each do |lvar_name|
9144
+ refute parser.static_env.declared?(lvar_name),
9145
+ "(#{version}) local variable #{lvar_name.to_s.inspect} has to be undefined before asserting"
9146
+ end
9147
+
9148
+ before = parser.static_env.instance_variable_get(:@variables).to_a
9149
+
9150
+ begin
9151
+ parsed_ast = parser.parse(source_file)
9152
+ rescue Parser::SyntaxError => exc
9153
+ backtrace = exc.backtrace
9154
+ Exception.instance_method(:initialize).bind(exc).
9155
+ call("(#{version}) #{exc.message}")
9156
+ exc.set_backtrace(backtrace)
9157
+ raise
9158
+ end
9159
+
9160
+ lvar_names.each do |lvar_name|
9161
+ assert parser.static_env.declared?(lvar_name),
9162
+ "(#{version}) expected local variable #{lvar_name.to_s.inspect} to be defined after parsing"
9163
+ end
9164
+
9165
+ after = parser.static_env.instance_variable_get(:@variables).to_a
9166
+ extra = after - before - lvar_names
9167
+
9168
+ assert extra.empty?,
9169
+ "(#{version}) expected only #{lvar_names.inspect} " \
9170
+ "to be defined during parsing, but also got #{extra.inspect}"
9171
+ end
9172
+ end
9173
+
9174
+ def test_pattern_matching_creates_locals
9175
+ assert_pattern_matching_defines_local_variables(
9176
+ %q{in a, *b, c},
9177
+ [:a, :b, :c]
9178
+ )
9179
+
9180
+ assert_pattern_matching_defines_local_variables(
9181
+ %q{in d | e | f},
9182
+ [:d, :e, :f]
9183
+ )
9184
+
9185
+ assert_pattern_matching_defines_local_variables(
9186
+ %q{in { g:, **h }},
9187
+ [:g, :h]
9188
+ )
9189
+
9190
+ assert_pattern_matching_defines_local_variables(
9191
+ %q{in A(i, *j, k)},
9192
+ [:i, :j, :k]
9193
+ )
9194
+
9195
+ assert_pattern_matching_defines_local_variables(
9196
+ %q{in 1 => l},
9197
+ [:l]
9198
+ )
9199
+
9200
+ assert_pattern_matching_defines_local_variables(
9201
+ %q{in "m":},
9202
+ [:m]
9203
+ )
9204
+ end
9205
+
9206
+ def test_pattern_matching__FILE__LINE_literals
9207
+ assert_parses(
9208
+ s(:case_match,
9209
+ s(:array,
9210
+ s(:str, "(assert_parses)"),
9211
+ s(:send,
9212
+ s(:int, 1), :+,
9213
+ s(:int, 1)),
9214
+ s(:__ENCODING__)),
9215
+ s(:in_pattern,
9216
+ s(:array_pattern,
9217
+ s(:str, "(assert_parses)"),
9218
+ s(:int, 2),
9219
+ s(:__ENCODING__)), nil, nil), nil),
9220
+ <<-RUBY,
9221
+ case [__FILE__, __LINE__ + 1, __ENCODING__]
9222
+ in [__FILE__, __LINE__, __ENCODING__]
9223
+ end
9224
+ RUBY
9225
+ %q{},
9226
+ SINCE_2_7)
9227
+ end
9228
+
9229
+ def test_pattern_matching_nil_pattern
9230
+ assert_parses_pattern_match(
9231
+ s(:in_pattern,
9232
+ s(:hash_pattern,
9233
+ s(:match_nil_pattern)),
9234
+ nil,
9235
+ s(:true)),
9236
+ %q{in **nil then true},
9237
+ %q{ ~~~~~ expression (in_pattern.hash_pattern.match_nil_pattern)
9238
+ | ~~~ name (in_pattern.hash_pattern.match_nil_pattern)}
9239
+ )
9240
+ end
9241
+
9242
+ def test_pattern_matching_single_line
9243
+ assert_parses(
9244
+ s(:begin,
9245
+ s(:in_match,
9246
+ s(:int, 1),
9247
+ s(:array_pattern,
9248
+ s(:match_var, :a))),
9249
+ s(:lvar, :a)),
9250
+ %q{1 in [a]; a},
9251
+ %q{~~~~~~~~ expression (in_match)
9252
+ | ~~ operator (in_match)},
9253
+ SINCE_2_7)
9254
+ end
9255
+
9256
+ def test_ruby_bug_pattern_matching_restore_in_kwarg_flag
9257
+ refute_diagnoses(
9258
+ "p(({} in {a:}), a:\n 1)",
9259
+ SINCE_2_7)
9260
+ end
9261
+
9262
+ def test_pattern_matching_duplicate_variable_name
9263
+ assert_diagnoses(
9264
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9265
+ %q{case 0; in a, a; end},
9266
+ %q{ ^ location},
9267
+ SINCE_2_7)
9268
+
9269
+ refute_diagnoses(
9270
+ %q{case [0, 1, 2, 3]; in _, _, _a, _a; end},
9271
+ SINCE_2_7)
9272
+
9273
+ assert_diagnoses(
9274
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9275
+ %q{case 0; in a, {a:}; end},
9276
+ %q{ ^ location},
9277
+ SINCE_2_7)
9278
+
9279
+ assert_diagnoses(
9280
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9281
+ %q{case 0; in a, {"a":}; end},
9282
+ %q{ ^ location},
9283
+ SINCE_2_7)
9284
+
9285
+ assert_diagnoses(
9286
+ [:error, :duplicate_variable_name, { :name => 'a' }],
9287
+ %q{0 in [a, a]},
9288
+ %q{ ^ location},
9289
+ SINCE_2_7)
9290
+ end
9291
+
9292
+ def test_pattern_matching_duplicate_hash_keys
9293
+ assert_diagnoses(
9294
+ [:error, :duplicate_pattern_key, { :name => 'a' }],
9295
+ %q{ case 0; in a: 1, a: 2; end },
9296
+ %q{ ^^ location},
9297
+ SINCE_2_7)
9298
+
9299
+ assert_diagnoses(
9300
+ [:error, :duplicate_pattern_key, { :name => 'a' }],
9301
+ %q{ case 0; in a: 1, "a": 2; end },
9302
+ %q{ ^^^^ location},
9303
+ SINCE_2_7)
9304
+
9305
+ assert_diagnoses(
9306
+ [:error, :duplicate_pattern_key, { :name => 'a' }],
9307
+ %q{ case 0; in "a": 1, "a": 2; end },
9308
+ %q{ ^^^^ location},
9309
+ SINCE_2_7)
9310
+
9311
+ assert_diagnoses(
9312
+ [:error, :duplicate_pattern_key, { :name => "a\0" }],
9313
+ %q{ case 0; in "a\x0":a1, "a\0":a2; end },
9314
+ %q{ ^^^^^^ location},
9315
+ SINCE_2_7)
9316
+
9317
+ assert_diagnoses(
9318
+ [:error, :duplicate_pattern_key, { :name => "abc" }],
9319
+ %q{ case 0; in "abc":a1, "a#{"b"}c":a2; end },
9320
+ %q{ ^^^^^^^^^^^ location},
9321
+ SINCE_2_7)
9322
+ end
9323
+
9324
+ def test_pattern_matching_required_parentheses_for_in_match
9325
+ assert_diagnoses(
9326
+ [:error, :unexpected_token, { :token => 'tCOMMA' }],
9327
+ %{1 in a, b},
9328
+ %{ ^ location},
9329
+ SINCE_2_7)
9330
+
9331
+ assert_diagnoses(
9332
+ [:error, :unexpected_token, { :token => 'tLABEL' }],
9333
+ %{1 in a:},
9334
+ %{ ^^ location},
9335
+ SINCE_2_7)
9336
+ end
9337
+
9338
+ def test_pattern_matching_required_bound_variable_before_pin
9339
+ assert_diagnoses(
9340
+ [:error, :undefined_lvar, { :name => 'a' }],
9341
+ %{case 0; in ^a; true; end},
9342
+ %{ ^ location},
9343
+ SINCE_2_7)
9344
+ end
9345
+
9346
+ def test_parser_bug_645
9347
+ assert_parses(
9348
+ s(:block,
9349
+ s(:lambda),
9350
+ s(:args,
9351
+ s(:optarg, :arg,
9352
+ s(:hash))), nil),
9353
+ '-> (arg={}) {}',
9354
+ %{},
9355
+ SINCE_1_9)
9356
+ end
7644
9357
  end