parser 2.7.0.5 → 2.7.1.4

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