parser 2.7.1.0 → 2.7.1.5

Sign up to get free protection for your applications and to get access to all the features.
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