parser 2.6.4.1 → 2.7.0.3

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