parser 2.7.0.5 → 2.7.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +21 -32
  4. data/CHANGELOG.md +59 -1
  5. data/README.md +2 -2
  6. data/Rakefile +2 -1
  7. data/doc/AST_FORMAT.md +106 -3
  8. data/lib/parser.rb +1 -0
  9. data/lib/parser/all.rb +1 -0
  10. data/lib/parser/ast/processor.rb +9 -0
  11. data/lib/parser/builders/default.rb +103 -12
  12. data/lib/parser/context.rb +1 -0
  13. data/lib/parser/current.rb +13 -4
  14. data/lib/parser/diagnostic.rb +1 -1
  15. data/lib/parser/diagnostic/engine.rb +1 -2
  16. data/lib/parser/lexer.rl +15 -1
  17. data/lib/parser/macruby.y +14 -4
  18. data/lib/parser/messages.rb +15 -0
  19. data/lib/parser/meta.rb +4 -4
  20. data/lib/parser/ruby18.y +2 -0
  21. data/lib/parser/ruby19.y +14 -4
  22. data/lib/parser/ruby20.y +14 -4
  23. data/lib/parser/ruby21.y +9 -2
  24. data/lib/parser/ruby22.y +9 -2
  25. data/lib/parser/ruby23.y +9 -2
  26. data/lib/parser/ruby24.y +9 -2
  27. data/lib/parser/ruby25.y +9 -2
  28. data/lib/parser/ruby26.y +9 -2
  29. data/lib/parser/ruby27.y +28 -8
  30. data/lib/parser/ruby28.y +3043 -0
  31. data/lib/parser/rubymotion.y +14 -4
  32. data/lib/parser/runner.rb +26 -2
  33. data/lib/parser/runner/ruby_rewrite.rb +2 -2
  34. data/lib/parser/source/buffer.rb +3 -1
  35. data/lib/parser/source/comment/associator.rb +14 -4
  36. data/lib/parser/source/map/endless_definition.rb +23 -0
  37. data/lib/parser/source/range.rb +17 -1
  38. data/lib/parser/source/tree_rewriter.rb +115 -12
  39. data/lib/parser/source/tree_rewriter/action.rb +135 -26
  40. data/lib/parser/tree_rewriter.rb +1 -2
  41. data/lib/parser/version.rb +1 -1
  42. data/parser.gemspec +3 -2
  43. data/test/helper.rb +49 -6
  44. data/test/parse_helper.rb +27 -23
  45. data/test/test_ast_processor.rb +32 -0
  46. data/test/test_base.rb +1 -1
  47. data/test/test_current.rb +2 -0
  48. data/test/test_diagnostic.rb +6 -7
  49. data/test/test_diagnostic_engine.rb +5 -8
  50. data/test/test_lexer.rb +17 -8
  51. data/test/test_meta.rb +12 -0
  52. data/test/test_parser.rb +477 -54
  53. data/test/test_runner_parse.rb +22 -1
  54. data/test/test_runner_rewrite.rb +1 -1
  55. data/test/test_source_buffer.rb +4 -1
  56. data/test/test_source_comment.rb +2 -2
  57. data/test/test_source_comment_associator.rb +47 -15
  58. data/test/test_source_map.rb +1 -2
  59. data/test/test_source_range.rb +29 -9
  60. data/test/test_source_rewriter.rb +4 -4
  61. data/test/test_source_rewriter_action.rb +2 -2
  62. data/test/test_source_tree_rewriter.rb +201 -13
  63. metadata +19 -12
@@ -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
@@ -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_2_8 = SINCE_2_7 - %w(2.7)
32
33
 
33
34
  # Guidelines for test naming:
34
35
  # * Test structure follows structure of AST_FORMAT.md.
@@ -5359,8 +5360,7 @@ class TestParser < Minitest::Test
5359
5360
 
5360
5361
  def test_crlf_line_endings
5361
5362
  with_versions(ALL_VERSIONS) do |_ver, parser|
5362
- source_file = Parser::Source::Buffer.new('(comments)')
5363
- source_file.source = "\r\nfoo"
5363
+ source_file = Parser::Source::Buffer.new('(comments)', source: "\r\nfoo")
5364
5364
 
5365
5365
  range = lambda do |from, to|
5366
5366
  Parser::Source::Range.new(source_file, from, to)
@@ -5433,8 +5433,7 @@ class TestParser < Minitest::Test
5433
5433
  with_versions(ALL_VERSIONS) do |_ver, parser|
5434
5434
  parser.builder.emit_file_line_as_literals = false
5435
5435
 
5436
- source_file = Parser::Source::Buffer.new('(comments)')
5437
- source_file.source = "[__FILE__, __LINE__]"
5436
+ source_file = Parser::Source::Buffer.new('(comments)', source: "[__FILE__, __LINE__]")
5438
5437
 
5439
5438
  ast = parser.parse(source_file)
5440
5439
 
@@ -5518,8 +5517,7 @@ class TestParser < Minitest::Test
5518
5517
 
5519
5518
  def assert_parses_with_comments(ast_pattern, source, comments_pattern)
5520
5519
  with_versions(ALL_VERSIONS) do |_ver, parser|
5521
- source_file = Parser::Source::Buffer.new('(comments)')
5522
- source_file.source = source
5520
+ source_file = Parser::Source::Buffer.new('(comments)', source: source)
5523
5521
 
5524
5522
  comments_pattern_here = comments_pattern.map do |(from, to)|
5525
5523
  range = Parser::Source::Range.new(source_file, from, to)
@@ -5550,8 +5548,8 @@ class TestParser < Minitest::Test
5550
5548
 
5551
5549
  def test_tokenize
5552
5550
  with_versions(ALL_VERSIONS) do |_ver, parser|
5553
- source_file = Parser::Source::Buffer.new('(tokenize)')
5554
- source_file.source = "1 + # foo\n 2"
5551
+ source_file = Parser::Source::Buffer.new('(tokenize)',
5552
+ source: "1 + # foo\n 2")
5555
5553
 
5556
5554
  range = lambda do |from, to|
5557
5555
  Parser::Source::Range.new(source_file, from, to)
@@ -5577,8 +5575,8 @@ class TestParser < Minitest::Test
5577
5575
 
5578
5576
  def test_tokenize_recover
5579
5577
  with_versions(ALL_VERSIONS) do |_ver, parser|
5580
- source_file = Parser::Source::Buffer.new('(tokenize)')
5581
- source_file.source = "1 + # foo\n "
5578
+ source_file = Parser::Source::Buffer.new('(tokenize)',
5579
+ source: "1 + # foo\n ")
5582
5580
 
5583
5581
  range = lambda do |from, to|
5584
5582
  Parser::Source::Range.new(source_file, from, to)
@@ -6553,39 +6551,64 @@ class TestParser < Minitest::Test
6553
6551
 
6554
6552
  def test_context_class
6555
6553
  [
6556
- %q{class A;},
6557
- %q{class A < B;}
6554
+ %q{class A; get_context; end},
6555
+ %q{class A < B; get_context; end}
6558
6556
  ].each do |code|
6559
6557
  assert_context([:class], code, ALL_VERSIONS)
6560
6558
  end
6561
6559
  end
6562
6560
 
6561
+ def test_context_module
6562
+ assert_context(
6563
+ [:module],
6564
+ %q{module M; get_context; end},
6565
+ ALL_VERSIONS)
6566
+ end
6567
+
6563
6568
  def test_context_sclass
6564
6569
  assert_context(
6565
6570
  [:sclass],
6566
- %q{class << foo;},
6571
+ %q{class << foo; get_context; end},
6567
6572
  ALL_VERSIONS)
6568
6573
  end
6569
6574
 
6570
6575
  def test_context_def
6571
- assert_context(
6572
- [:def],
6573
- %q{def m;},
6574
- ALL_VERSIONS)
6576
+ [
6577
+ %q{def m; get_context; end},
6578
+ %q{def m(a = get_context); end}
6579
+ ].each do |code|
6580
+ assert_context([:def], code, ALL_VERSIONS)
6581
+ end
6582
+
6583
+ [
6584
+ %q{def m() = get_context},
6585
+ %q{def m(a = get_context) = 42}
6586
+ ].each do |code|
6587
+ assert_context([:def], code, SINCE_2_8)
6588
+ end
6575
6589
  end
6576
6590
 
6577
6591
  def test_context_defs
6578
- assert_context(
6579
- [:defs],
6580
- %q{def foo.m;},
6581
- ALL_VERSIONS)
6592
+ [
6593
+ %q{def foo.m; get_context; end},
6594
+ %q{def foo.m(a = get_context); end}
6595
+ ].each do |code|
6596
+ assert_context([:defs], code, ALL_VERSIONS)
6597
+ end
6598
+
6599
+ [
6600
+ %q{def foo.m() = get_context},
6601
+ %q{def foo.m(a = get_context) = 42}
6602
+ ].each do |code|
6603
+ assert_context([:defs], code, SINCE_2_8)
6604
+ end
6582
6605
  end
6583
6606
 
6584
6607
  def test_context_cmd_brace_block
6585
6608
  [
6586
- 'tap foo {',
6587
- 'foo.tap foo {',
6588
- 'foo::tap foo {'
6609
+ 'tap foo { get_context }',
6610
+ 'foo.tap foo { get_context }',
6611
+ 'foo::tap foo { get_context }'
6589
6612
  ].each do |code|
6590
6613
  assert_context([:block], code, ALL_VERSIONS)
6591
6614
  end
@@ -6593,12 +6616,12 @@ class TestParser < Minitest::Test
6593
6616
 
6594
6617
  def test_context_brace_block
6595
6618
  [
6596
- 'tap {',
6597
- 'foo.tap {',
6598
- 'foo::tap {',
6599
- 'tap do',
6600
- 'foo.tap do',
6601
- 'foo::tap do'
6619
+ 'tap { get_context }',
6620
+ 'foo.tap { get_context }',
6621
+ 'foo::tap { get_context }',
6622
+ 'tap do get_context end',
6623
+ 'foo.tap do get_context end',
6624
+ 'foo::tap do get_context end'
6602
6625
  ].each do |code|
6603
6626
  assert_context([:block], code, ALL_VERSIONS)
6604
6627
  end
@@ -6606,9 +6629,9 @@ class TestParser < Minitest::Test
6606
6629
 
6607
6630
  def test_context_do_block
6608
6631
  [
6609
- %q{tap 1 do},
6610
- %q{foo.tap do},
6611
- %q{foo::tap do}
6632
+ %q{tap 1 do get_context end},
6633
+ %q{foo.tap do get_context end},
6634
+ %q{foo::tap do get_context end}
6612
6635
  ].each do |code|
6613
6636
  assert_context([:block], code, ALL_VERSIONS)
6614
6637
  end
@@ -6616,8 +6639,12 @@ class TestParser < Minitest::Test
6616
6639
 
6617
6640
  def test_context_lambda
6618
6641
  [
6619
- '->() {',
6620
- '->() do'
6642
+ '->() { get_context }',
6643
+ '->() do get_context end',
6644
+ '-> { get_context }',
6645
+ '-> do get_context end',
6646
+ '->(a = get_context) {}',
6647
+ '->(a = get_context) do end'
6621
6648
  ].each do |code|
6622
6649
  assert_context([:lambda], code, SINCE_1_9)
6623
6650
  end
@@ -6625,28 +6652,61 @@ class TestParser < Minitest::Test
6625
6652
 
6626
6653
  def test_context_nested
6627
6654
  assert_context(
6628
- [:class, :sclass, :defs, :def, :block],
6629
- %q{class A; class << foo; def bar.m; def m; tap do},
6655
+ [:class, :module, :sclass, :defs, :def, :block],
6656
+ %q{
6657
+ class A
6658
+ module M
6659
+ class << foo
6660
+ def bar.m
6661
+ def m
6662
+ tap do
6663
+ get_context
6664
+ end
6665
+ end
6666
+ end
6667
+ end
6668
+ end
6669
+ end
6670
+ },
6630
6671
  ALL_VERSIONS)
6631
6672
 
6632
6673
  assert_context(
6633
- [:class, :sclass, :defs, :def, :lambda, :block],
6634
- %q{class A; class << foo; def bar.m; def m; -> do; tap do},
6674
+ [:class, :module, :sclass, :defs, :def, :lambda, :block],
6675
+ %q{
6676
+ class A
6677
+ module M
6678
+ class << foo
6679
+ def bar.m
6680
+ def m
6681
+ -> do
6682
+ tap do
6683
+ get_context
6684
+ end
6685
+ end
6686
+ end
6687
+ end
6688
+ end
6689
+ end
6690
+ end
6691
+ },
6635
6692
  SINCE_1_9)
6636
6693
 
6637
6694
  assert_context(
6638
6695
  [],
6639
6696
  %q{
6640
6697
  class A
6641
- class << foo
6642
- def bar.m
6643
- def m
6644
- tap do
6698
+ module M
6699
+ class << foo
6700
+ def bar.m
6701
+ def m
6702
+ tap do
6703
+ end
6645
6704
  end
6646
6705
  end
6647
6706
  end
6648
6707
  end
6649
6708
  end
6709
+ get_context
6650
6710
  },
6651
6711
  ALL_VERSIONS)
6652
6712
 
@@ -6654,17 +6714,20 @@ class TestParser < Minitest::Test
6654
6714
  [],
6655
6715
  %q{
6656
6716
  class A
6657
- class << foo
6658
- def bar.m
6659
- def m
6660
- -> do
6661
- tap do
6717
+ module M
6718
+ class << foo
6719
+ def bar.m
6720
+ def m
6721
+ -> do
6722
+ tap do
6723
+ end
6662
6724
  end
6663
6725
  end
6664
6726
  end
6665
6727
  end
6666
6728
  end
6667
6729
  end
6730
+ get_context
6668
6731
  },
6669
6732
  SINCE_1_9)
6670
6733
  end
@@ -7748,7 +7811,8 @@ class TestParser < Minitest::Test
7748
7811
  end
7749
7812
  end
7750
7813
 
7751
- def test_forward_args
7814
+ def test_forward_args_legacy
7815
+ Parser::Builders::Default.emit_forward_arg = false
7752
7816
  assert_parses(
7753
7817
  s(:def, :foo,
7754
7818
  s(:forward_args),
@@ -7780,7 +7844,27 @@ class TestParser < Minitest::Test
7780
7844
  %q{def foo(...); end},
7781
7845
  %q{},
7782
7846
  SINCE_2_7)
7847
+ ensure
7848
+ Parser::Builders::Default.emit_forward_arg = true
7849
+ end
7850
+
7851
+ def test_forward_arg
7852
+ assert_parses(
7853
+ s(:def, :foo,
7854
+ s(:args,
7855
+ s(:forward_arg)),
7856
+ s(:send, nil, :bar,
7857
+ s(:forwarded_args))),
7858
+ %q{def foo(...); bar(...); end},
7859
+ %q{ ~ begin (args)
7860
+ | ~~~~~ expression (args)
7861
+ | ~ end (args)
7862
+ | ~~~ expression (args.forward_arg)
7863
+ | ~~~ expression (send.forwarded_args)},
7864
+ SINCE_2_7)
7865
+ end
7783
7866
 
7867
+ def test_forward_args_invalid
7784
7868
  assert_diagnoses(
7785
7869
  [:error, :block_and_blockarg],
7786
7870
  %q{def foo(...) bar(...) { }; end},
@@ -7806,6 +7890,12 @@ class TestParser < Minitest::Test
7806
7890
  %q{ ^^^ location},
7807
7891
  SINCE_2_7)
7808
7892
 
7893
+ assert_diagnoses(
7894
+ [:error, :unexpected_token, { :token => 'tBDOT3' }],
7895
+ %q{def foo(x,y,z); bar(x, y, z, ...); end},
7896
+ %q{ ^^^ location},
7897
+ SINCE_2_8)
7898
+
7809
7899
  assert_diagnoses(
7810
7900
  [:error, :unexpected_token, { :token => 'tBDOT3' }],
7811
7901
  %q{def foo(x,y,z); super(...); end},
@@ -7822,7 +7912,13 @@ class TestParser < Minitest::Test
7822
7912
  [:error, :unexpected_token, { :token => 'tBDOT3' }],
7823
7913
  %q{->(...) {}},
7824
7914
  %q{ ^^^ location},
7825
- SINCE_2_7)
7915
+ ['2.7'])
7916
+
7917
+ assert_diagnoses(
7918
+ [:error, :unexpected_token, { :token => 'tDOT3' }],
7919
+ %q{->(...) {}},
7920
+ %q{ ^^^ location},
7921
+ SINCE_2_8)
7826
7922
 
7827
7923
  # Here and below the parser asssumes that
7828
7924
  # it can be a beginningless range, so the error comes after reducing right paren
@@ -7875,6 +7971,26 @@ class TestParser < Minitest::Test
7875
7971
  SINCE_2_7)
7876
7972
  end
7877
7973
 
7974
+ def test_trailing_forward_arg
7975
+ assert_parses(
7976
+ s(:def, :foo,
7977
+ s(:args,
7978
+ s(:arg, :a),
7979
+ s(:arg, :b),
7980
+ s(:forward_arg)),
7981
+ s(:send, nil, :bar,
7982
+ s(:lvar, :a),
7983
+ s(:int, 42),
7984
+ s(:forwarded_args))),
7985
+ %q{def foo(a, b, ...); bar(a, 42, ...); end},
7986
+ %q{ ~ begin (args)
7987
+ | ~~~~~~~~~~~ expression (args)
7988
+ | ~ end (args)
7989
+ | ~~~ expression (args.forward_arg)},
7990
+ SINCE_2_8)
7991
+ end
7992
+
7993
+
7878
7994
  def test_erange_without_parentheses_at_eol
7879
7995
  assert_diagnoses(
7880
7996
  [:warning, :triple_dot_at_eol],
@@ -8344,7 +8460,7 @@ class TestParser < Minitest::Test
8344
8460
  nil),
8345
8461
  "#{case_pre}#{code}; end",
8346
8462
  source_maps,
8347
- SINCE_2_7
8463
+ versions
8348
8464
  )
8349
8465
  end
8350
8466
 
@@ -8675,6 +8791,18 @@ class TestParser < Minitest::Test
8675
8791
  | ~ end (in_pattern.hash_pattern)}
8676
8792
  )
8677
8793
 
8794
+ assert_parses_pattern_match(
8795
+ s(:in_pattern,
8796
+ s(:hash_pattern,
8797
+ s(:pair, s(:sym, :a), s(:int, 1))),
8798
+ nil,
8799
+ s(:true)),
8800
+ %q{in { a: 1, } then true},
8801
+ %q{ ~~~~~~~~~ expression (in_pattern.hash_pattern)
8802
+ | ~ begin (in_pattern.hash_pattern)
8803
+ | ~ end (in_pattern.hash_pattern)}
8804
+ )
8805
+
8678
8806
  assert_parses_pattern_match(
8679
8807
  s(:in_pattern,
8680
8808
  s(:hash_pattern,
@@ -8746,6 +8874,67 @@ class TestParser < Minitest::Test
8746
8874
  %q{in a: 1, _a:, ** then true},
8747
8875
  %q{ ~~~~~~~~~~~~~ expression (in_pattern.hash_pattern)}
8748
8876
  )
8877
+
8878
+ assert_parses_pattern_match(
8879
+ s(:in_pattern,
8880
+ s(:hash_pattern,
8881
+ s(:pair,
8882
+ s(:sym, :a),
8883
+ s(:int, 1))), nil,
8884
+ s(:false)),
8885
+ %q{
8886
+ in {a: 1
8887
+ }
8888
+ false
8889
+ },
8890
+ %q{}
8891
+ )
8892
+
8893
+
8894
+ assert_parses_pattern_match(
8895
+ s(:in_pattern,
8896
+ s(:hash_pattern,
8897
+ s(:pair,
8898
+ s(:sym, :a),
8899
+ s(:int, 2))), nil,
8900
+ s(:false)),
8901
+ %q{
8902
+ in {a:
8903
+ 2}
8904
+ false
8905
+ },
8906
+ %q{}
8907
+ )
8908
+
8909
+ assert_parses_pattern_match(
8910
+ s(:in_pattern,
8911
+ s(:hash_pattern,
8912
+ s(:pair,
8913
+ s(:sym, :a),
8914
+ s(:hash_pattern,
8915
+ s(:match_var, :b))),
8916
+ s(:match_var, :c)), nil,
8917
+ s(:send, nil, :p,
8918
+ s(:lvar, :c))),
8919
+ %q{
8920
+ in a: {b:}, c:
8921
+ p c
8922
+ },
8923
+ %q{}
8924
+ )
8925
+
8926
+ assert_parses_pattern_match(
8927
+ s(:in_pattern,
8928
+ s(:hash_pattern,
8929
+ s(:match_var, :a)), nil,
8930
+ s(:true)),
8931
+ %q{
8932
+ in {a:
8933
+ }
8934
+ true
8935
+ },
8936
+ %q{}
8937
+ )
8749
8938
  end
8750
8939
 
8751
8940
  def test_pattern_matching_hash_with_string_keys
@@ -8860,6 +9049,22 @@ class TestParser < Minitest::Test
8860
9049
  %q{ ~~~~~~~ location},
8861
9050
  SINCE_2_7
8862
9051
  )
9052
+
9053
+ assert_diagnoses(
9054
+ [:error, :pm_interp_in_var_name],
9055
+ %q{case a; in "#{a}": 1; end},
9056
+ %q{ ~~~~~~~ location},
9057
+ SINCE_2_7
9058
+ )
9059
+ end
9060
+
9061
+ def test_pattern_matching_invalid_lvar_name
9062
+ assert_diagnoses(
9063
+ [:error, :lvar_name, { name: :a? }],
9064
+ %q{case a; in a?:; end},
9065
+ %q{ ~~ location},
9066
+ SINCE_2_7
9067
+ )
8863
9068
  end
8864
9069
 
8865
9070
  def test_pattern_matching_keyword_variable
@@ -9137,8 +9342,7 @@ class TestParser < Minitest::Test
9137
9342
  code = "case 1; #{match_code}; then [#{lvar_names.join(', ')}]; end"
9138
9343
 
9139
9344
  with_versions(versions) do |version, parser|
9140
- source_file = Parser::Source::Buffer.new('(assert_context)')
9141
- source_file.source = code
9345
+ source_file = Parser::Source::Buffer.new('(assert_context)', source: code)
9142
9346
 
9143
9347
  lvar_names.each do |lvar_name|
9144
9348
  refute parser.static_env.declared?(lvar_name),
@@ -9148,7 +9352,7 @@ class TestParser < Minitest::Test
9148
9352
  before = parser.static_env.instance_variable_get(:@variables).to_a
9149
9353
 
9150
9354
  begin
9151
- parsed_ast = parser.parse(source_file)
9355
+ _parsed_ast = parser.parse(source_file)
9152
9356
  rescue Parser::SyntaxError => exc
9153
9357
  backtrace = exc.backtrace
9154
9358
  Exception.instance_method(:initialize).bind(exc).
@@ -9354,4 +9558,223 @@ class TestParser < Minitest::Test
9354
9558
  %{},
9355
9559
  SINCE_1_9)
9356
9560
  end
9561
+
9562
+ def test_endless_method
9563
+ assert_parses(
9564
+ s(:def_e, :foo,
9565
+ s(:args),
9566
+ s(:int, 42)),
9567
+ %q{def foo() = 42},
9568
+ %q{~~~ keyword
9569
+ | ~~~ name
9570
+ | ^ assignment
9571
+ |~~~~~~~~~~~~~~ expression},
9572
+ SINCE_2_8)
9573
+
9574
+ assert_parses(
9575
+ s(:def_e, :inc,
9576
+ s(:args, s(:arg, :x)),
9577
+ s(:send,
9578
+ s(:lvar, :x), :+,
9579
+ s(:int, 1))),
9580
+ %q{def inc(x) = x + 1},
9581
+ %q{~~~ keyword
9582
+ | ~~~ name
9583
+ | ^ assignment
9584
+ |~~~~~~~~~~~~~~~~~~ expression},
9585
+ SINCE_2_8)
9586
+
9587
+ assert_parses(
9588
+ s(:defs_e, s(:send, nil, :obj), :foo,
9589
+ s(:args),
9590
+ s(:int, 42)),
9591
+ %q{def obj.foo() = 42},
9592
+ %q{~~~ keyword
9593
+ | ^ operator
9594
+ | ~~~ name
9595
+ | ^ assignment
9596
+ |~~~~~~~~~~~~~~~~~~ expression},
9597
+ SINCE_2_8)
9598
+
9599
+ assert_parses(
9600
+ s(:defs_e, s(:send, nil, :obj), :inc,
9601
+ s(:args, s(:arg, :x)),
9602
+ s(:send,
9603
+ s(:lvar, :x), :+,
9604
+ s(:int, 1))),
9605
+ %q{def obj.inc(x) = x + 1},
9606
+ %q{~~~ keyword
9607
+ | ~~~ name
9608
+ | ^ operator
9609
+ | ^ assignment
9610
+ |~~~~~~~~~~~~~~~~~~~~~~ expression},
9611
+ SINCE_2_8)
9612
+ end
9613
+
9614
+ def test_endless_method_forwarded_args_legacy
9615
+ Parser::Builders::Default.emit_forward_arg = false
9616
+ assert_parses(
9617
+ s(:def_e, :foo,
9618
+ s(:forward_args),
9619
+ s(:send, nil, :bar,
9620
+ s(:forwarded_args))),
9621
+ %q{def foo(...) = bar(...)},
9622
+ %q{~~~ keyword
9623
+ | ~~~ name
9624
+ | ^ assignment
9625
+ |~~~~~~~~~~~~~~~~~~~~~~~ expression},
9626
+ SINCE_2_8)
9627
+ Parser::Builders::Default.emit_forward_arg = true
9628
+ end
9629
+
9630
+ def test_endless_method_without_brackets
9631
+ assert_diagnoses(
9632
+ [:error, :unexpected_token, { :token => 'tEQL' }],
9633
+ %Q{def foo = 42},
9634
+ %q{ ^ location},
9635
+ SINCE_2_8)
9636
+
9637
+ assert_diagnoses(
9638
+ [:error, :unexpected_token, { :token => 'tEQL' }],
9639
+ %Q{def obj.foo = 42},
9640
+ %q{ ^ location},
9641
+ SINCE_2_8
9642
+ )
9643
+ end
9644
+
9645
+ def test_endless_method_with_rescue_mod
9646
+ assert_parses(
9647
+ s(:def_e, :m,
9648
+ s(:args),
9649
+ s(:rescue,
9650
+ s(:int, 1),
9651
+ s(:resbody, nil, nil,
9652
+ s(:int, 2)), nil)),
9653
+ %q{def m() = 1 rescue 2},
9654
+ %q{},
9655
+ SINCE_2_8)
9656
+
9657
+ assert_parses(
9658
+ s(:defs_e,
9659
+ s(:self), :m,
9660
+ s(:args),
9661
+ s(:rescue,
9662
+ s(:int, 1),
9663
+ s(:resbody, nil, nil,
9664
+ s(:int, 2)), nil)),
9665
+ %q{def self.m() = 1 rescue 2},
9666
+ %q{},
9667
+ SINCE_2_8)
9668
+ end
9669
+
9670
+ def test_rasgn
9671
+ assert_parses(
9672
+ s(:rasgn,
9673
+ s(:int, 1), s(:lvasgn, :a)),
9674
+ %q{1 => a},
9675
+ %q{~~~~~~ expression
9676
+ | ^^ operator},
9677
+ SINCE_2_8)
9678
+
9679
+ assert_parses(
9680
+ s(:rasgn,
9681
+ s(:send, s(:int, 1), :+, s(:int, 2)),
9682
+ s(:gvasgn, :$a)),
9683
+ %q{1 + 2 => $a},
9684
+ %q{~~~~~~~~~~~ expression
9685
+ | ^^ operator},
9686
+ SINCE_2_8)
9687
+ end
9688
+
9689
+ def test_mrasgn
9690
+ assert_parses(
9691
+ s(:mrasgn,
9692
+ s(:send, s(:int, 13), :divmod, s(:int, 5)),
9693
+ s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b))),
9694
+ %q{13.divmod(5) => a,b},
9695
+ %q{~~~~~~~~~~~~~~~~~~~ expression
9696
+ | ^^ operator},
9697
+ SINCE_2_8)
9698
+
9699
+ assert_parses(
9700
+ s(:mrasgn,
9701
+ s(:mrasgn,
9702
+ s(:send, s(:int, 13), :divmod, s(:int, 5)),
9703
+ s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b))),
9704
+ s(:mlhs, s(:lvasgn, :c), s(:lvasgn, :d))),
9705
+ %q{13.divmod(5) => a,b => c, d},
9706
+ %q{~~~~~~~~~~~~~~~~~~~ expression (mrasgn)
9707
+ |~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression},
9708
+ SINCE_2_8)
9709
+ end
9710
+
9711
+ def test_rasgn_line_continuation
9712
+ assert_diagnoses(
9713
+ [:error, :unexpected_token, { :token => 'tASSOC' }],
9714
+ %Q{13.divmod(5)\n=> a,b; [a, b]},
9715
+ %{ ^^ location},
9716
+ SINCE_2_8)
9717
+ end
9718
+
9719
+ def test_find_pattern
9720
+ assert_parses_pattern_match(
9721
+ s(:in_pattern,
9722
+ s(:find_pattern,
9723
+ s(:match_rest,
9724
+ s(:match_var, :x)),
9725
+ s(:match_as,
9726
+ s(:int, 1),
9727
+ s(:match_var, :a)),
9728
+ s(:match_rest,
9729
+ s(:match_var, :y))),
9730
+ nil,
9731
+ s(:true)),
9732
+ %q{in [*x, 1 => a, *y] then true},
9733
+ %q{ ~~~~~~~~~~~~~~~~ expression (in_pattern.find_pattern)
9734
+ | ~ begin (in_pattern.find_pattern)
9735
+ | ~ end (in_pattern.find_pattern)
9736
+ | ~~ expression (in_pattern.find_pattern.match_rest/1)
9737
+ | ~~ expression (in_pattern.find_pattern.match_rest/2)},
9738
+ SINCE_2_8)
9739
+
9740
+ assert_parses_pattern_match(
9741
+ s(:in_pattern,
9742
+ s(:const_pattern,
9743
+ s(:const, nil, :String),
9744
+ s(:find_pattern,
9745
+ s(:match_rest),
9746
+ s(:int, 1),
9747
+ s(:match_rest))),
9748
+ nil,
9749
+ s(:true)),
9750
+ %q{in String(*, 1, *) then true},
9751
+ %q{ ~~~~~~~ expression (in_pattern.const_pattern.find_pattern)},
9752
+ SINCE_2_8)
9753
+
9754
+ assert_parses_pattern_match(
9755
+ s(:in_pattern,
9756
+ s(:const_pattern,
9757
+ s(:const, nil, :Array),
9758
+ s(:find_pattern,
9759
+ s(:match_rest),
9760
+ s(:int, 1),
9761
+ s(:match_rest))),
9762
+ nil,
9763
+ s(:true)),
9764
+ %q{in Array[*, 1, *] then true},
9765
+ %q{ ~~~~~~~ expression (in_pattern.const_pattern.find_pattern)},
9766
+ SINCE_2_8)
9767
+
9768
+ assert_parses_pattern_match(
9769
+ s(:in_pattern,
9770
+ s(:find_pattern,
9771
+ s(:match_rest),
9772
+ s(:int, 42),
9773
+ s(:match_rest)),
9774
+ nil,
9775
+ s(:true)),
9776
+ %q{in *, 42, * then true},
9777
+ %q{ ~~~~~~~~ expression (in_pattern.find_pattern)},
9778
+ SINCE_2_8)
9779
+ end
9357
9780
  end