parser 2.7.1.0 → 2.7.1.5

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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +10 -11
  3. data/CHANGELOG.md +70 -1
  4. data/README.md +2 -2
  5. data/Rakefile +2 -1
  6. data/doc/AST_FORMAT.md +107 -3
  7. data/lib/parser.rb +1 -0
  8. data/lib/parser/all.rb +1 -0
  9. data/lib/parser/ast/processor.rb +2 -0
  10. data/lib/parser/base.rb +6 -5
  11. data/lib/parser/builders/default.rb +146 -19
  12. data/lib/parser/context.rb +1 -0
  13. data/lib/parser/current.rb +9 -0
  14. data/lib/parser/diagnostic.rb +1 -1
  15. data/lib/parser/diagnostic/engine.rb +1 -2
  16. data/lib/parser/lexer.rb +23770 -0
  17. data/lib/parser/lexer.rl +15 -1
  18. data/lib/parser/macruby.rb +6149 -0
  19. data/lib/parser/macruby.y +15 -5
  20. data/lib/parser/max_numparam_stack.rb +1 -1
  21. data/lib/parser/messages.rb +17 -0
  22. data/lib/parser/meta.rb +3 -3
  23. data/lib/parser/ruby18.rb +5663 -0
  24. data/lib/parser/ruby18.y +3 -1
  25. data/lib/parser/ruby19.rb +6092 -0
  26. data/lib/parser/ruby19.y +15 -5
  27. data/lib/parser/ruby20.rb +6527 -0
  28. data/lib/parser/ruby20.y +15 -5
  29. data/lib/parser/ruby21.rb +6578 -0
  30. data/lib/parser/ruby21.y +10 -3
  31. data/lib/parser/ruby22.rb +6613 -0
  32. data/lib/parser/ruby22.y +10 -3
  33. data/lib/parser/ruby23.rb +6624 -0
  34. data/lib/parser/ruby23.y +10 -3
  35. data/lib/parser/ruby24.rb +6694 -0
  36. data/lib/parser/ruby24.y +10 -3
  37. data/lib/parser/ruby25.rb +6662 -0
  38. data/lib/parser/ruby25.y +10 -3
  39. data/lib/parser/ruby26.rb +6676 -0
  40. data/lib/parser/ruby26.y +10 -3
  41. data/lib/parser/ruby27.rb +7803 -0
  42. data/lib/parser/ruby27.y +16 -8
  43. data/lib/parser/ruby30.rb +8052 -0
  44. data/lib/parser/ruby30.y +3048 -0
  45. data/lib/parser/rubymotion.rb +6086 -0
  46. data/lib/parser/rubymotion.y +15 -5
  47. data/lib/parser/runner.rb +26 -2
  48. data/lib/parser/runner/ruby_rewrite.rb +2 -2
  49. data/lib/parser/source/buffer.rb +3 -1
  50. data/lib/parser/source/comment.rb +1 -1
  51. data/lib/parser/source/comment/associator.rb +14 -4
  52. data/lib/parser/source/map/method_definition.rb +25 -0
  53. data/lib/parser/source/range.rb +19 -3
  54. data/lib/parser/source/tree_rewriter.rb +115 -12
  55. data/lib/parser/source/tree_rewriter/action.rb +135 -26
  56. data/lib/parser/tree_rewriter.rb +1 -2
  57. data/lib/parser/version.rb +1 -1
  58. data/parser.gemspec +6 -2
  59. data/test/helper.rb +49 -6
  60. data/test/parse_helper.rb +49 -40
  61. data/test/test_ast_processor.rb +32 -0
  62. data/test/test_base.rb +1 -1
  63. data/test/test_current.rb +2 -0
  64. data/test/test_diagnostic.rb +6 -7
  65. data/test/test_diagnostic_engine.rb +5 -8
  66. data/test/test_lexer.rb +17 -8
  67. data/test/test_meta.rb +12 -0
  68. data/test/test_parse_helper.rb +12 -9
  69. data/test/test_parser.rb +612 -56
  70. data/test/test_runner_parse.rb +22 -1
  71. data/test/test_runner_rewrite.rb +1 -1
  72. data/test/test_source_buffer.rb +4 -1
  73. data/test/test_source_comment.rb +2 -2
  74. data/test/test_source_comment_associator.rb +47 -15
  75. data/test/test_source_map.rb +1 -2
  76. data/test/test_source_range.rb +29 -9
  77. data/test/test_source_rewriter.rb +4 -4
  78. data/test/test_source_rewriter_action.rb +2 -2
  79. data/test/test_source_tree_rewriter.rb +201 -13
  80. metadata +19 -13
  81. data/.gitignore +0 -33
@@ -37,9 +37,8 @@ class TestLexer < Minitest::Test
37
37
  end
38
38
 
39
39
  def assert_escape(expected, input)
40
- source_buffer = Parser::Source::Buffer.new('(assert_escape)')
41
-
42
- source_buffer.source = "\"\\#{input}\"".encode(input.encoding)
40
+ source_buffer = Parser::Source::Buffer.new('(assert_escape)',
41
+ source: "\"\\#{input}\"".encode(input.encoding))
43
42
 
44
43
  @lex.reset
45
44
  @lex.source_buffer = source_buffer
@@ -71,8 +70,7 @@ class TestLexer < Minitest::Test
71
70
  end
72
71
 
73
72
  def assert_scanned(input, *args)
74
- source_buffer = Parser::Source::Buffer.new('(assert_scanned)')
75
- source_buffer.source = input
73
+ source_buffer = Parser::Source::Buffer.new('(assert_scanned)', source: input)
76
74
 
77
75
  @lex.reset(false)
78
76
  @lex.source_buffer = source_buffer
@@ -3569,14 +3567,25 @@ class TestLexer < Minitest::Test
3569
3567
  :tIDENTIFIER, 're', [1, 3])
3570
3568
  end
3571
3569
 
3570
+ def test_endless_method
3571
+ setup_lexer(30)
3572
+
3573
+ assert_scanned('def foo() = 42',
3574
+ :kDEF, "def", [0, 3],
3575
+ :tIDENTIFIER, "foo", [4, 7],
3576
+ :tLPAREN2, "(", [7, 8],
3577
+ :tRPAREN, ")", [8, 9],
3578
+ :tEQL, "=", [10, 11],
3579
+ :tINTEGER, 42, [12, 14])
3580
+ end
3581
+
3572
3582
  def lex_numbered_parameter(input)
3573
3583
  @lex.max_numparam_stack.push
3574
3584
 
3575
3585
  @lex.context = Parser::Context.new
3576
3586
  @lex.context.push(:block)
3577
3587
 
3578
- source_buffer = Parser::Source::Buffer.new('(assert_lex_numbered_parameter)')
3579
- source_buffer.source = input
3588
+ source_buffer = Parser::Source::Buffer.new('(assert_lex_numbered_parameter)', source: input)
3580
3589
 
3581
3590
  @lex.source_buffer = source_buffer
3582
3591
 
@@ -3594,7 +3603,7 @@ class TestLexer < Minitest::Test
3594
3603
 
3595
3604
  def refute_scanned_numbered_parameter(input, message = nil)
3596
3605
  err = assert_raises Parser::SyntaxError do
3597
- lex_token, (lex_value, lex_range) = lex_numbered_parameter(input)
3606
+ _lex_token, (_lex_value, _lex_range) = lex_numbered_parameter(input)
3598
3607
  end
3599
3608
 
3600
3609
  if message
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'helper'
4
+
5
+ class TestMeta < Minitest::Test
6
+ def test_NODE_TYPES
7
+ for_each_node do |node|
8
+ assert Parser::Meta::NODE_TYPES.include?(node.type),
9
+ "Type #{node.type} missing from Parser::Meta::NODE_TYPES"
10
+ end
11
+ end
12
+ end
@@ -25,33 +25,36 @@ class TestParseHelper < Minitest::Test
25
25
  end
26
26
 
27
27
  def test_parse_mapsation_description
28
- assert_equal [[0, 4, 'expr', [], '~~~~ expr']],
28
+ assert_equal [[0...4, 'expr', [], '~~~~ expr']],
29
29
  parse_maps('~~~~ expr')
30
30
 
31
- assert_equal [[0, 4, 'expr', [], '^~~~ expr']],
31
+ assert_equal [[0...4, 'expr', [], '^~~~ expr']],
32
32
  parse_maps('^~~~ expr')
33
33
 
34
- assert_equal [[0, 4, 'expr', [], '^^^^ expr']],
34
+ assert_equal [[0...4, 'expr', [], '^^^^ expr']],
35
35
  parse_maps('^^^^ expr')
36
36
 
37
- assert_equal [[2, 3, 'op', [], ' ^ op']],
37
+ assert_equal [[2...3, 'op', [], ' ^ op']],
38
38
  parse_maps(' ^ op')
39
39
 
40
- assert_equal [[2, 3, 'op', ['foo'], ' ~ op (foo)']],
40
+ assert_equal [[2...3, 'op', ['foo'], ' ~ op (foo)']],
41
41
  parse_maps(' ~ op (foo)')
42
42
 
43
- assert_equal [[2, 4, 'op', ['foo', 'bar'], ' ~~ op (foo.bar)']],
43
+ assert_equal [[2...4, 'op', ['foo', 'bar'], ' ~~ op (foo.bar)']],
44
44
  parse_maps(' ~~ op (foo.bar)')
45
45
 
46
- assert_equal [[2, 4, 'op', ['foo/2', 'bar'], ' ~~ op (foo/2.bar)']],
46
+ assert_equal [[2...4, 'op', ['foo/2', 'bar'], ' ~~ op (foo/2.bar)']],
47
47
  parse_maps(' ~~ op (foo/2.bar)')
48
48
 
49
- assert_equal [[0, 4, 'expr', [], '~~~~ expr'],
50
- [5, 7, 'op', ['str', 'e_h'], ' ~~ op (str.e_h)']],
49
+ assert_equal [[0...4, 'expr', [], '~~~~ expr'],
50
+ [5...7, 'op', ['str', 'e_h'], ' ~~ op (str.e_h)']],
51
51
  parse_maps(%{
52
52
  |~~~~ expr
53
53
  | ~~ op (str.e_h)
54
54
  })
55
+
56
+ assert_equal [[nil, 'expr', [], '! expr']],
57
+ parse_maps('! expr')
55
58
  end
56
59
 
57
60
  def test_traverse_ast
@@ -29,6 +29,7 @@ class TestParser < Minitest::Test
29
29
  SINCE_2_5 = SINCE_2_4 - %w(2.4)
30
30
  SINCE_2_6 = SINCE_2_5 - %w(2.5)
31
31
  SINCE_2_7 = SINCE_2_6 - %w(2.6)
32
+ SINCE_3_0 = SINCE_2_7 - %w(2.7)
32
33
 
33
34
  # Guidelines for test naming:
34
35
  # * Test structure follows structure of AST_FORMAT.md.
@@ -1855,6 +1856,7 @@ class TestParser < Minitest::Test
1855
1856
  %q{def foo; end},
1856
1857
  %q{~~~ keyword
1857
1858
  | ~~~ name
1859
+ |! assignment
1858
1860
  | ~~~ end})
1859
1861
 
1860
1862
  assert_parses(
@@ -1975,7 +1977,9 @@ class TestParser < Minitest::Test
1975
1977
  %q{alias :foo bar},
1976
1978
  %q{~~~~~ keyword
1977
1979
  | ~~~~ expression (sym/1)
1980
+ | ^ begin (sym/1)
1978
1981
  | ~~~ expression (sym/2)
1982
+ | ! begin (sym/2)
1979
1983
  |~~~~~~~~~~~~~~ expression})
1980
1984
  end
1981
1985
 
@@ -5359,8 +5363,7 @@ class TestParser < Minitest::Test
5359
5363
 
5360
5364
  def test_crlf_line_endings
5361
5365
  with_versions(ALL_VERSIONS) do |_ver, parser|
5362
- source_file = Parser::Source::Buffer.new('(comments)')
5363
- source_file.source = "\r\nfoo"
5366
+ source_file = Parser::Source::Buffer.new('(comments)', source: "\r\nfoo")
5364
5367
 
5365
5368
  range = lambda do |from, to|
5366
5369
  Parser::Source::Range.new(source_file, from, to)
@@ -5433,8 +5436,7 @@ class TestParser < Minitest::Test
5433
5436
  with_versions(ALL_VERSIONS) do |_ver, parser|
5434
5437
  parser.builder.emit_file_line_as_literals = false
5435
5438
 
5436
- source_file = Parser::Source::Buffer.new('(comments)')
5437
- source_file.source = "[__FILE__, __LINE__]"
5439
+ source_file = Parser::Source::Buffer.new('(comments)', source: "[__FILE__, __LINE__]")
5438
5440
 
5439
5441
  ast = parser.parse(source_file)
5440
5442
 
@@ -5518,8 +5520,7 @@ class TestParser < Minitest::Test
5518
5520
 
5519
5521
  def assert_parses_with_comments(ast_pattern, source, comments_pattern)
5520
5522
  with_versions(ALL_VERSIONS) do |_ver, parser|
5521
- source_file = Parser::Source::Buffer.new('(comments)')
5522
- source_file.source = source
5523
+ source_file = Parser::Source::Buffer.new('(comments)', source: source)
5523
5524
 
5524
5525
  comments_pattern_here = comments_pattern.map do |(from, to)|
5525
5526
  range = Parser::Source::Range.new(source_file, from, to)
@@ -5550,8 +5551,8 @@ class TestParser < Minitest::Test
5550
5551
 
5551
5552
  def test_tokenize
5552
5553
  with_versions(ALL_VERSIONS) do |_ver, parser|
5553
- source_file = Parser::Source::Buffer.new('(tokenize)')
5554
- source_file.source = "1 + # foo\n 2"
5554
+ source_file = Parser::Source::Buffer.new('(tokenize)',
5555
+ source: "1 + # foo\n 2")
5555
5556
 
5556
5557
  range = lambda do |from, to|
5557
5558
  Parser::Source::Range.new(source_file, from, to)
@@ -5577,8 +5578,8 @@ class TestParser < Minitest::Test
5577
5578
 
5578
5579
  def test_tokenize_recover
5579
5580
  with_versions(ALL_VERSIONS) do |_ver, parser|
5580
- source_file = Parser::Source::Buffer.new('(tokenize)')
5581
- source_file.source = "1 + # foo\n "
5581
+ source_file = Parser::Source::Buffer.new('(tokenize)',
5582
+ source: "1 + # foo\n ")
5582
5583
 
5583
5584
  range = lambda do |from, to|
5584
5585
  Parser::Source::Range.new(source_file, from, to)
@@ -6553,39 +6554,64 @@ class TestParser < Minitest::Test
6553
6554
 
6554
6555
  def test_context_class
6555
6556
  [
6556
- %q{class A;},
6557
- %q{class A < B;}
6557
+ %q{class A; get_context; end},
6558
+ %q{class A < B; get_context; end}
6558
6559
  ].each do |code|
6559
6560
  assert_context([:class], code, ALL_VERSIONS)
6560
6561
  end
6561
6562
  end
6562
6563
 
6564
+ def test_context_module
6565
+ assert_context(
6566
+ [:module],
6567
+ %q{module M; get_context; end},
6568
+ ALL_VERSIONS)
6569
+ end
6570
+
6563
6571
  def test_context_sclass
6564
6572
  assert_context(
6565
6573
  [:sclass],
6566
- %q{class << foo;},
6574
+ %q{class << foo; get_context; end},
6567
6575
  ALL_VERSIONS)
6568
6576
  end
6569
6577
 
6570
6578
  def test_context_def
6571
- assert_context(
6572
- [:def],
6573
- %q{def m;},
6574
- ALL_VERSIONS)
6579
+ [
6580
+ %q{def m; get_context; end},
6581
+ %q{def m(a = get_context); end}
6582
+ ].each do |code|
6583
+ assert_context([:def], code, ALL_VERSIONS)
6584
+ end
6585
+
6586
+ [
6587
+ %q{def m() = get_context},
6588
+ %q{def m(a = get_context) = 42}
6589
+ ].each do |code|
6590
+ assert_context([:def], code, SINCE_3_0)
6591
+ end
6575
6592
  end
6576
6593
 
6577
6594
  def test_context_defs
6578
- assert_context(
6579
- [:defs],
6580
- %q{def foo.m;},
6581
- ALL_VERSIONS)
6595
+ [
6596
+ %q{def foo.m; get_context; end},
6597
+ %q{def foo.m(a = get_context); end}
6598
+ ].each do |code|
6599
+ assert_context([:defs], code, ALL_VERSIONS)
6600
+ end
6601
+
6602
+ [
6603
+ %q{def foo.m() = get_context},
6604
+ %q{def foo.m(a = get_context) = 42}
6605
+ ].each do |code|
6606
+ assert_context([:defs], code, SINCE_3_0)
6607
+ end
6582
6608
  end
6583
6609
 
6584
6610
  def test_context_cmd_brace_block
6585
6611
  [
6586
- 'tap foo {',
6587
- 'foo.tap foo {',
6588
- 'foo::tap foo {'
6612
+ 'tap foo { get_context }',
6613
+ 'foo.tap foo { get_context }',
6614
+ 'foo::tap foo { get_context }'
6589
6615
  ].each do |code|
6590
6616
  assert_context([:block], code, ALL_VERSIONS)
6591
6617
  end
@@ -6593,12 +6619,12 @@ class TestParser < Minitest::Test
6593
6619
 
6594
6620
  def test_context_brace_block
6595
6621
  [
6596
- 'tap {',
6597
- 'foo.tap {',
6598
- 'foo::tap {',
6599
- 'tap do',
6600
- 'foo.tap do',
6601
- 'foo::tap do'
6622
+ 'tap { get_context }',
6623
+ 'foo.tap { get_context }',
6624
+ 'foo::tap { get_context }',
6625
+ 'tap do get_context end',
6626
+ 'foo.tap do get_context end',
6627
+ 'foo::tap do get_context end'
6602
6628
  ].each do |code|
6603
6629
  assert_context([:block], code, ALL_VERSIONS)
6604
6630
  end
@@ -6606,9 +6632,9 @@ class TestParser < Minitest::Test
6606
6632
 
6607
6633
  def test_context_do_block
6608
6634
  [
6609
- %q{tap 1 do},
6610
- %q{foo.tap do},
6611
- %q{foo::tap do}
6635
+ %q{tap 1 do get_context end},
6636
+ %q{foo.tap do get_context end},
6637
+ %q{foo::tap do get_context end}
6612
6638
  ].each do |code|
6613
6639
  assert_context([:block], code, ALL_VERSIONS)
6614
6640
  end
@@ -6616,8 +6642,12 @@ class TestParser < Minitest::Test
6616
6642
 
6617
6643
  def test_context_lambda
6618
6644
  [
6619
- '->() {',
6620
- '->() do'
6645
+ '->() { get_context }',
6646
+ '->() do get_context end',
6647
+ '-> { get_context }',
6648
+ '-> do get_context end',
6649
+ '->(a = get_context) {}',
6650
+ '->(a = get_context) do end'
6621
6651
  ].each do |code|
6622
6652
  assert_context([:lambda], code, SINCE_1_9)
6623
6653
  end
@@ -6625,28 +6655,61 @@ class TestParser < Minitest::Test
6625
6655
 
6626
6656
  def test_context_nested
6627
6657
  assert_context(
6628
- [:class, :sclass, :defs, :def, :block],
6629
- %q{class A; class << foo; def bar.m; def m; tap do},
6658
+ [:class, :module, :sclass, :defs, :def, :block],
6659
+ %q{
6660
+ class A
6661
+ module M
6662
+ class << foo
6663
+ def bar.m
6664
+ def m
6665
+ tap do
6666
+ get_context
6667
+ end
6668
+ end
6669
+ end
6670
+ end
6671
+ end
6672
+ end
6673
+ },
6630
6674
  ALL_VERSIONS)
6631
6675
 
6632
6676
  assert_context(
6633
- [:class, :sclass, :defs, :def, :lambda, :block],
6634
- %q{class A; class << foo; def bar.m; def m; -> do; tap do},
6677
+ [:class, :module, :sclass, :defs, :def, :lambda, :block],
6678
+ %q{
6679
+ class A
6680
+ module M
6681
+ class << foo
6682
+ def bar.m
6683
+ def m
6684
+ -> do
6685
+ tap do
6686
+ get_context
6687
+ end
6688
+ end
6689
+ end
6690
+ end
6691
+ end
6692
+ end
6693
+ end
6694
+ },
6635
6695
  SINCE_1_9)
6636
6696
 
6637
6697
  assert_context(
6638
6698
  [],
6639
6699
  %q{
6640
6700
  class A
6641
- class << foo
6642
- def bar.m
6643
- def m
6644
- tap do
6701
+ module M
6702
+ class << foo
6703
+ def bar.m
6704
+ def m
6705
+ tap do
6706
+ end
6645
6707
  end
6646
6708
  end
6647
6709
  end
6648
6710
  end
6649
6711
  end
6712
+ get_context
6650
6713
  },
6651
6714
  ALL_VERSIONS)
6652
6715
 
@@ -6654,17 +6717,20 @@ class TestParser < Minitest::Test
6654
6717
  [],
6655
6718
  %q{
6656
6719
  class A
6657
- class << foo
6658
- def bar.m
6659
- def m
6660
- -> do
6661
- tap do
6720
+ module M
6721
+ class << foo
6722
+ def bar.m
6723
+ def m
6724
+ -> do
6725
+ tap do
6726
+ end
6662
6727
  end
6663
6728
  end
6664
6729
  end
6665
6730
  end
6666
6731
  end
6667
6732
  end
6733
+ get_context
6668
6734
  },
6669
6735
  SINCE_1_9)
6670
6736
  end
@@ -7448,7 +7514,7 @@ class TestParser < Minitest::Test
7448
7514
  s(:nil))),
7449
7515
  %q{proc {_1 = nil}},
7450
7516
  %q{},
7451
- SINCE_2_7)
7517
+ %w(2.7))
7452
7518
 
7453
7519
  assert_diagnoses(
7454
7520
  [:error, :cant_assign_to_numparam, { :name => '_1' }],
@@ -7476,7 +7542,7 @@ class TestParser < Minitest::Test
7476
7542
 
7477
7543
  refute_diagnoses(
7478
7544
  %q{proc { _1 = nil; _1}},
7479
- SINCE_2_7)
7545
+ %w(2.7))
7480
7546
  end
7481
7547
 
7482
7548
  def test_numparams_in_nested_blocks
@@ -7748,7 +7814,8 @@ class TestParser < Minitest::Test
7748
7814
  end
7749
7815
  end
7750
7816
 
7751
- def test_forward_args
7817
+ def test_forward_args_legacy
7818
+ Parser::Builders::Default.emit_forward_arg = false
7752
7819
  assert_parses(
7753
7820
  s(:def, :foo,
7754
7821
  s(:forward_args),
@@ -7780,7 +7847,27 @@ class TestParser < Minitest::Test
7780
7847
  %q{def foo(...); end},
7781
7848
  %q{},
7782
7849
  SINCE_2_7)
7850
+ ensure
7851
+ Parser::Builders::Default.emit_forward_arg = true
7852
+ end
7853
+
7854
+ def test_forward_arg
7855
+ assert_parses(
7856
+ s(:def, :foo,
7857
+ s(:args,
7858
+ s(:forward_arg)),
7859
+ s(:send, nil, :bar,
7860
+ s(:forwarded_args))),
7861
+ %q{def foo(...); bar(...); end},
7862
+ %q{ ~ begin (args)
7863
+ | ~~~~~ expression (args)
7864
+ | ~ end (args)
7865
+ | ~~~ expression (args.forward_arg)
7866
+ | ~~~ expression (send.forwarded_args)},
7867
+ SINCE_2_7)
7868
+ end
7783
7869
 
7870
+ def test_forward_args_invalid
7784
7871
  assert_diagnoses(
7785
7872
  [:error, :block_and_blockarg],
7786
7873
  %q{def foo(...) bar(...) { }; end},
@@ -7806,6 +7893,12 @@ class TestParser < Minitest::Test
7806
7893
  %q{ ^^^ location},
7807
7894
  SINCE_2_7)
7808
7895
 
7896
+ assert_diagnoses(
7897
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7898
+ %q{def foo(x,y,z); bar(x, y, z, ...); end},
7899
+ %q{ ^^^ location},
7900
+ SINCE_3_0)
7901
+
7809
7902
  assert_diagnoses(
7810
7903
  [:error, :unexpected_token, { :token => 'tBDOT3' }],
7811
7904
  %q{def foo(x,y,z); super(...); end},
@@ -7822,7 +7915,13 @@ class TestParser < Minitest::Test
7822
7915
  [:error, :unexpected_token, { :token => 'tBDOT3' }],
7823
7916
  %q{->(...) {}},
7824
7917
  %q{ ^^^ location},
7825
- SINCE_2_7)
7918
+ ['2.7'])
7919
+
7920
+ assert_diagnoses(
7921
+ [:error, :unexpected_token, { :token => 'tDOT3' }],
7922
+ %q{->(...) {}},
7923
+ %q{ ^^^ location},
7924
+ SINCE_3_0)
7826
7925
 
7827
7926
  # Here and below the parser asssumes that
7828
7927
  # it can be a beginningless range, so the error comes after reducing right paren
@@ -7875,6 +7974,26 @@ class TestParser < Minitest::Test
7875
7974
  SINCE_2_7)
7876
7975
  end
7877
7976
 
7977
+ def test_trailing_forward_arg
7978
+ assert_parses(
7979
+ s(:def, :foo,
7980
+ s(:args,
7981
+ s(:arg, :a),
7982
+ s(:arg, :b),
7983
+ s(:forward_arg)),
7984
+ s(:send, nil, :bar,
7985
+ s(:lvar, :a),
7986
+ s(:int, 42),
7987
+ s(:forwarded_args))),
7988
+ %q{def foo(a, b, ...); bar(a, 42, ...); end},
7989
+ %q{ ~ begin (args)
7990
+ | ~~~~~~~~~~~ expression (args)
7991
+ | ~ end (args)
7992
+ | ~~~ expression (args.forward_arg)},
7993
+ SINCE_3_0)
7994
+ end
7995
+
7996
+
7878
7997
  def test_erange_without_parentheses_at_eol
7879
7998
  assert_diagnoses(
7880
7999
  [:warning, :triple_dot_at_eol],
@@ -8344,7 +8463,7 @@ class TestParser < Minitest::Test
8344
8463
  nil),
8345
8464
  "#{case_pre}#{code}; end",
8346
8465
  source_maps,
8347
- SINCE_2_7
8466
+ versions
8348
8467
  )
8349
8468
  end
8350
8469
 
@@ -8790,6 +8909,21 @@ class TestParser < Minitest::Test
8790
8909
  %q{}
8791
8910
  )
8792
8911
 
8912
+ assert_parses_pattern_match(
8913
+ s(:in_pattern,
8914
+ s(:hash_pattern,
8915
+ s(:pair,
8916
+ s(:sym, :Foo),
8917
+ s(:int, 42))), nil,
8918
+ s(:false)),
8919
+ %q{
8920
+ in {Foo: 42
8921
+ }
8922
+ false
8923
+ },
8924
+ %q{}
8925
+ )
8926
+
8793
8927
  assert_parses_pattern_match(
8794
8928
  s(:in_pattern,
8795
8929
  s(:hash_pattern,
@@ -8933,6 +9067,22 @@ class TestParser < Minitest::Test
8933
9067
  %q{ ~~~~~~~ location},
8934
9068
  SINCE_2_7
8935
9069
  )
9070
+
9071
+ assert_diagnoses(
9072
+ [:error, :pm_interp_in_var_name],
9073
+ %q{case a; in "#{a}": 1; end},
9074
+ %q{ ~~~~~~~ location},
9075
+ SINCE_2_7
9076
+ )
9077
+ end
9078
+
9079
+ def test_pattern_matching_invalid_lvar_name
9080
+ assert_diagnoses(
9081
+ [:error, :lvar_name, { name: :a? }],
9082
+ %q{case a; in a?:; end},
9083
+ %q{ ~~ location},
9084
+ SINCE_2_7
9085
+ )
8936
9086
  end
8937
9087
 
8938
9088
  def test_pattern_matching_keyword_variable
@@ -9210,8 +9360,7 @@ class TestParser < Minitest::Test
9210
9360
  code = "case 1; #{match_code}; then [#{lvar_names.join(', ')}]; end"
9211
9361
 
9212
9362
  with_versions(versions) do |version, parser|
9213
- source_file = Parser::Source::Buffer.new('(assert_context)')
9214
- source_file.source = code
9363
+ source_file = Parser::Source::Buffer.new('(assert_context)', source: code)
9215
9364
 
9216
9365
  lvar_names.each do |lvar_name|
9217
9366
  refute parser.static_env.declared?(lvar_name),
@@ -9221,7 +9370,7 @@ class TestParser < Minitest::Test
9221
9370
  before = parser.static_env.instance_variable_get(:@variables).to_a
9222
9371
 
9223
9372
  begin
9224
- parsed_ast = parser.parse(source_file)
9373
+ _parsed_ast = parser.parse(source_file)
9225
9374
  rescue Parser::SyntaxError => exc
9226
9375
  backtrace = exc.backtrace
9227
9376
  Exception.instance_method(:initialize).bind(exc).
@@ -9427,4 +9576,411 @@ class TestParser < Minitest::Test
9427
9576
  %{},
9428
9577
  SINCE_1_9)
9429
9578
  end
9579
+
9580
+ def test_endless_method
9581
+ assert_parses(
9582
+ s(:def, :foo,
9583
+ s(:args),
9584
+ s(:int, 42)),
9585
+ %q{def foo() = 42},
9586
+ %q{~~~ keyword
9587
+ | ~~~ name
9588
+ | ^ assignment
9589
+ |! end
9590
+ |~~~~~~~~~~~~~~ expression},
9591
+ SINCE_3_0)
9592
+
9593
+ assert_parses(
9594
+ s(:def, :inc,
9595
+ s(:args, s(:arg, :x)),
9596
+ s(:send,
9597
+ s(:lvar, :x), :+,
9598
+ s(:int, 1))),
9599
+ %q{def inc(x) = x + 1},
9600
+ %q{~~~ keyword
9601
+ | ~~~ name
9602
+ | ^ assignment
9603
+ |~~~~~~~~~~~~~~~~~~ expression},
9604
+ SINCE_3_0)
9605
+
9606
+ assert_parses(
9607
+ s(:defs, s(:send, nil, :obj), :foo,
9608
+ s(:args),
9609
+ s(:int, 42)),
9610
+ %q{def obj.foo() = 42},
9611
+ %q{~~~ keyword
9612
+ | ^ operator
9613
+ | ~~~ name
9614
+ | ^ assignment
9615
+ |~~~~~~~~~~~~~~~~~~ expression},
9616
+ SINCE_3_0)
9617
+
9618
+ assert_parses(
9619
+ s(:defs, s(:send, nil, :obj), :inc,
9620
+ s(:args, s(:arg, :x)),
9621
+ s(:send,
9622
+ s(:lvar, :x), :+,
9623
+ s(:int, 1))),
9624
+ %q{def obj.inc(x) = x + 1},
9625
+ %q{~~~ keyword
9626
+ | ~~~ name
9627
+ | ^ operator
9628
+ | ^ assignment
9629
+ |~~~~~~~~~~~~~~~~~~~~~~ expression},
9630
+ SINCE_3_0)
9631
+ end
9632
+
9633
+ def test_endless_method_forwarded_args_legacy
9634
+ Parser::Builders::Default.emit_forward_arg = false
9635
+ assert_parses(
9636
+ s(:def, :foo,
9637
+ s(:forward_args),
9638
+ s(:send, nil, :bar,
9639
+ s(:forwarded_args))),
9640
+ %q{def foo(...) = bar(...)},
9641
+ %q{~~~ keyword
9642
+ | ~~~ name
9643
+ | ^ assignment
9644
+ |~~~~~~~~~~~~~~~~~~~~~~~ expression},
9645
+ SINCE_3_0)
9646
+ Parser::Builders::Default.emit_forward_arg = true
9647
+ end
9648
+
9649
+ def test_endless_method_without_brackets
9650
+ assert_diagnoses(
9651
+ [:error, :unexpected_token, { :token => 'tEQL' }],
9652
+ %Q{def foo = 42},
9653
+ %q{ ^ location},
9654
+ SINCE_3_0)
9655
+
9656
+ assert_diagnoses(
9657
+ [:error, :unexpected_token, { :token => 'tEQL' }],
9658
+ %Q{def obj.foo = 42},
9659
+ %q{ ^ location},
9660
+ SINCE_3_0
9661
+ )
9662
+ end
9663
+
9664
+ def test_endless_method_with_rescue_mod
9665
+ assert_parses(
9666
+ s(:def, :m,
9667
+ s(:args),
9668
+ s(:rescue,
9669
+ s(:int, 1),
9670
+ s(:resbody, nil, nil,
9671
+ s(:int, 2)), nil)),
9672
+ %q{def m() = 1 rescue 2},
9673
+ %q{},
9674
+ SINCE_3_0)
9675
+
9676
+ assert_parses(
9677
+ s(:defs,
9678
+ s(:self), :m,
9679
+ s(:args),
9680
+ s(:rescue,
9681
+ s(:int, 1),
9682
+ s(:resbody, nil, nil,
9683
+ s(:int, 2)), nil)),
9684
+ %q{def self.m() = 1 rescue 2},
9685
+ %q{},
9686
+ SINCE_3_0)
9687
+ end
9688
+
9689
+ def test_rasgn
9690
+ assert_parses(
9691
+ s(:lvasgn, :a,
9692
+ s(:int, 1)),
9693
+ %q{1 => a},
9694
+ %q{~~~~~~ expression
9695
+ | ^^ operator},
9696
+ SINCE_3_0)
9697
+
9698
+ assert_parses(
9699
+ s(:gvasgn, :$a,
9700
+ s(:send, s(:int, 1), :+, s(:int, 2))),
9701
+ %q{1 + 2 => $a},
9702
+ %q{~~~~~~~~~~~ expression
9703
+ | ^^ operator},
9704
+ SINCE_3_0)
9705
+ end
9706
+
9707
+ def test_mrasgn
9708
+ assert_parses(
9709
+ s(:masgn,
9710
+ s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b)),
9711
+ s(:send, s(:int, 13), :divmod, s(:int, 5))),
9712
+ %q{13.divmod(5) => a,b},
9713
+ %q{~~~~~~~~~~~~~~~~~~~ expression
9714
+ | ^^ operator},
9715
+ SINCE_3_0)
9716
+
9717
+ assert_parses(
9718
+ s(:masgn,
9719
+ s(:mlhs, s(:lvasgn, :c), s(:lvasgn, :d)),
9720
+ s(:masgn,
9721
+ s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b)),
9722
+ s(:send, s(:int, 13), :divmod, s(:int, 5))),
9723
+ ),
9724
+ %q{13.divmod(5) => a,b => c, d},
9725
+ %q{~~~~~~~~~~~~~~~~~~~ expression (masgn)
9726
+ |~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression},
9727
+ SINCE_3_0)
9728
+ end
9729
+
9730
+ def test_rasgn_line_continuation
9731
+ assert_diagnoses(
9732
+ [:error, :unexpected_token, { :token => 'tASSOC' }],
9733
+ %Q{13.divmod(5)\n=> a,b; [a, b]},
9734
+ %{ ^^ location},
9735
+ SINCE_3_0)
9736
+ end
9737
+
9738
+ def test_find_pattern
9739
+ assert_parses_pattern_match(
9740
+ s(:in_pattern,
9741
+ s(:find_pattern,
9742
+ s(:match_rest,
9743
+ s(:match_var, :x)),
9744
+ s(:match_as,
9745
+ s(:int, 1),
9746
+ s(:match_var, :a)),
9747
+ s(:match_rest,
9748
+ s(:match_var, :y))),
9749
+ nil,
9750
+ s(:true)),
9751
+ %q{in [*x, 1 => a, *y] then true},
9752
+ %q{ ~~~~~~~~~~~~~~~~ expression (in_pattern.find_pattern)
9753
+ | ~ begin (in_pattern.find_pattern)
9754
+ | ~ end (in_pattern.find_pattern)
9755
+ | ~~ expression (in_pattern.find_pattern.match_rest/1)
9756
+ | ~~ expression (in_pattern.find_pattern.match_rest/2)},
9757
+ SINCE_3_0)
9758
+
9759
+ assert_parses_pattern_match(
9760
+ s(:in_pattern,
9761
+ s(:const_pattern,
9762
+ s(:const, nil, :String),
9763
+ s(:find_pattern,
9764
+ s(:match_rest),
9765
+ s(:int, 1),
9766
+ s(:match_rest))),
9767
+ nil,
9768
+ s(:true)),
9769
+ %q{in String(*, 1, *) then true},
9770
+ %q{ ~~~~~~~ expression (in_pattern.const_pattern.find_pattern)},
9771
+ SINCE_3_0)
9772
+
9773
+ assert_parses_pattern_match(
9774
+ s(:in_pattern,
9775
+ s(:const_pattern,
9776
+ s(:const, nil, :Array),
9777
+ s(:find_pattern,
9778
+ s(:match_rest),
9779
+ s(:int, 1),
9780
+ s(:match_rest))),
9781
+ nil,
9782
+ s(:true)),
9783
+ %q{in Array[*, 1, *] then true},
9784
+ %q{ ~~~~~~~ expression (in_pattern.const_pattern.find_pattern)},
9785
+ SINCE_3_0)
9786
+
9787
+ assert_parses_pattern_match(
9788
+ s(:in_pattern,
9789
+ s(:find_pattern,
9790
+ s(:match_rest),
9791
+ s(:int, 42),
9792
+ s(:match_rest)),
9793
+ nil,
9794
+ s(:true)),
9795
+ %q{in *, 42, * then true},
9796
+ %q{ ~~~~~~~~ expression (in_pattern.find_pattern)},
9797
+ SINCE_3_0)
9798
+ end
9799
+
9800
+ def test_invalid_source
9801
+ with_versions(ALL_VERSIONS) do |_ver, parser|
9802
+ source_file = Parser::Source::Buffer.new('(comments)', source: "def foo; en")
9803
+
9804
+ parser.diagnostics.all_errors_are_fatal = false
9805
+ ast = parser.parse(source_file)
9806
+ assert_nil(ast)
9807
+ end
9808
+ end
9809
+
9810
+ def test_reserved_for_numparam__before_30
9811
+ assert_parses(
9812
+ s(:block,
9813
+ s(:send, nil, :proc),
9814
+ s(:args),
9815
+ s(:lvasgn, :_1,
9816
+ s(:nil))),
9817
+ %q{proc {_1 = nil}},
9818
+ %q{},
9819
+ ALL_VERSIONS - SINCE_3_0)
9820
+
9821
+ assert_parses(
9822
+ s(:lvasgn, :_2,
9823
+ s(:int, 1)),
9824
+ %q{_2 = 1},
9825
+ %q{},
9826
+ ALL_VERSIONS - SINCE_3_0)
9827
+
9828
+ assert_parses(
9829
+ s(:block,
9830
+ s(:send, nil, :proc),
9831
+ s(:args,
9832
+ s(:procarg0,
9833
+ s(:arg, :_3))), nil),
9834
+ %q{proc {|_3|}},
9835
+ %q{},
9836
+ SINCE_1_9 - SINCE_3_0)
9837
+
9838
+ assert_parses(
9839
+ s(:def, :x,
9840
+ s(:args,
9841
+ s(:arg, :_4)), nil),
9842
+ %q{def x(_4) end},
9843
+ %q{},
9844
+ ALL_VERSIONS - SINCE_3_0)
9845
+
9846
+ assert_parses(
9847
+ s(:def, :_5,
9848
+ s(:args), nil),
9849
+ %q{def _5; end},
9850
+ %q{},
9851
+ ALL_VERSIONS - SINCE_3_0)
9852
+
9853
+ assert_parses(
9854
+ s(:defs,
9855
+ s(:self), :_6,
9856
+ s(:args), nil),
9857
+ %q{def self._6; end},
9858
+ %q{},
9859
+ ALL_VERSIONS - SINCE_3_0)
9860
+ end
9861
+
9862
+ def test_reserved_for_numparam__since_30
9863
+ # Regular assignments:
9864
+
9865
+ assert_diagnoses(
9866
+ [:error, :reserved_for_numparam, { :name => '_1' }],
9867
+ %q{proc {_1 = nil}},
9868
+ %q{ ^^ location},
9869
+ SINCE_3_0)
9870
+
9871
+ assert_diagnoses(
9872
+ [:error, :reserved_for_numparam, { :name => '_2' }],
9873
+ %q{_2 = 1},
9874
+ %q{^^ location},
9875
+ SINCE_3_0)
9876
+
9877
+ # Arguments:
9878
+
9879
+ [
9880
+ # req (procarg0)
9881
+ [
9882
+ %q{proc {|_3|}},
9883
+ %q{ ^^ location},
9884
+ ],
9885
+
9886
+ # req
9887
+ [
9888
+ %q{proc {|_3,|}},
9889
+ %q{ ^^ location},
9890
+ ],
9891
+
9892
+ # opt
9893
+ [
9894
+ %q{proc {|_3 = 42|}},
9895
+ %q{ ^^ location},
9896
+ ],
9897
+
9898
+ # mlhs
9899
+ [
9900
+ %q{proc {|(_3)|}},
9901
+ %q{ ^^ location},
9902
+ ],
9903
+
9904
+ # rest
9905
+ [
9906
+ %q{proc {|*_3|}},
9907
+ %q{ ^^ location},
9908
+ ],
9909
+
9910
+ # kwarg
9911
+ [
9912
+ %q{proc {|_3:|}},
9913
+ %q{ ^^^ location},
9914
+ ],
9915
+
9916
+ # kwoptarg
9917
+ [
9918
+ %q{proc {|_3: 42|}},
9919
+ %q{ ^^^ location},
9920
+ ],
9921
+
9922
+ # kwrestarg
9923
+ [
9924
+ %q{proc {|**_3|}},
9925
+ %q{ ^^ location},
9926
+ ],
9927
+
9928
+ # block
9929
+ [
9930
+ %q{proc {|&_3|}},
9931
+ %q{ ^^ location},
9932
+ ],
9933
+
9934
+ # shadowarg
9935
+ [
9936
+ %q{proc {|;_3|}},
9937
+ %q{ ^^ location},
9938
+ ],
9939
+ ].each do |(code, location)|
9940
+ assert_diagnoses(
9941
+ [:error, :reserved_for_numparam, { :name => '_3' }],
9942
+ code,
9943
+ location,
9944
+ SINCE_3_0)
9945
+ end
9946
+
9947
+ # Method definitions:
9948
+
9949
+ [
9950
+ # regular method
9951
+ [
9952
+ %q{def _5; end},
9953
+ %q{ ^^ location}
9954
+ ],
9955
+ # regular singleton method
9956
+ [
9957
+ %q{def self._5; end},
9958
+ %q{ ^^ location}
9959
+ ],
9960
+ # endless method
9961
+ [
9962
+ %q{def _5() = nil},
9963
+ %q{ ^^ location}
9964
+ ],
9965
+ # endless singleton method
9966
+ [
9967
+ %q{def self._5() = nil},
9968
+ %q{ ^^ location}
9969
+ ],
9970
+ ].each do |(code, location)|
9971
+ assert_diagnoses(
9972
+ [:error, :reserved_for_numparam, { :name => '_5' }],
9973
+ code,
9974
+ location,
9975
+ SINCE_3_0)
9976
+ end
9977
+ end
9978
+
9979
+ def test_endless_setter
9980
+ assert_diagnoses(
9981
+ [:error, :endless_setter],
9982
+ %q{def foo=() = 42},
9983
+ %q{ ^^^^ location},
9984
+ SINCE_3_0)
9985
+ end
9430
9986
  end