diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2016-05-15 10:24:44 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2016-05-16 19:41:42 +0900 |
commit | 334cb185b7189ab5449210b77e684ec8559712f4 (patch) | |
tree | a42a0a5a617ed22ff1c5410bd115238ae9d521ab | |
parent | e143a741913fd970e27eb83e3d809d9694038f9f (diff) | |
download | ruby-topic/ripper-unnamed-kwrest.tar.gz |
ripper: dispatch new parser event 'kwrest_param' on f_kwresttopic/ripper-unnamed-kwrest
Ripper has an issue in handling bare kwrest:
$ ruby -rpp -rripper -e'pp Ripper.sexp("def a(**) end")'
[:program,
[[:def,
[:@ident, "a", [1, 4]],
[:paren, [:params, nil, nil, nil, nil, nil, 183, nil]],
[:bodystmt, [[:void_stmt]], nil, nil, nil]]]]
The mysterious 183 is the problem: this is an ID generated by
internal_id(). This patch introduces a new 'kwrest_param' parser event
that works just like 'rest_param' event that corresponds to rest params
(def a(*rest) end). After applying this, the result will be:
$ ruby -rpp -rripper -e'pp Ripper.sexp("def a(**name) end")'
[:program,
[[:def,
[:@ident, "a", [1, 4]],
[:paren,
[:params,
nil,
nil,
nil,
nil,
nil,
[:kwrest_param, [:@ident, "name", [1, 8]]],
nil]],
[:bodystmt, [[:void_stmt]], nil, nil, nil]]]]
$ ruby -rpp -rripper -e'pp Ripper.sexp("def a(**) end")'
[:program,
[[:def,
[:@ident, "a", [1, 4]],
[:paren, [:params, nil, nil, nil, nil, nil, [:kwrest_param, nil], nil]],
[:bodystmt, [[:void_stmt]], nil, nil, nil]]]]
* parse.y (f_kwrest): dispatch kwrest_param event, just like rest_param.
* test/ripper/dummyparser.rb (on_kwrest_param): add kwrest_param parser
event handler.
* test/ripper/test_parser_events.rb (test_params): adjust.
* test/ripper/test_parser_events.rb (test_kwrest_param): test that
kwrest_param event handler is properly called.
-rw-r--r-- | parse.y | 8 | ||||
-rw-r--r-- | test/ripper/dummyparser.rb | 4 | ||||
-rw-r--r-- | test/ripper/test_parser_events.rb | 11 |
3 files changed, 22 insertions, 1 deletions
@@ -4853,12 +4853,20 @@ kwrest_mark : tPOW f_kwrest : kwrest_mark tIDENTIFIER { shadowing_lvar(get_id($2)); + /*%%%*/ $$ = $2; + /*% + $$ = dispatch1(kwrest_param, $2); + %*/ } | kwrest_mark { + /*%%%*/ $$ = internal_id(); arg_var($$); + /*% + $$ = dispatch1(kwrest_param, Qnil); + %*/ } ; diff --git a/test/ripper/dummyparser.rb b/test/ripper/dummyparser.rb index 3c196d9a23..9d9de7f641 100644 --- a/test/ripper/dummyparser.rb +++ b/test/ripper/dummyparser.rb @@ -148,6 +148,10 @@ class DummyParser < Ripper "*#{var}" end + def on_kwrest_param(var) + "**#{var}" + end + def on_blockarg(var) "&#{var}" end diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb index 540d36e4d9..070f4d7614 100644 --- a/test/ripper/test_parser_events.rb +++ b/test/ripper/test_parser_events.rb @@ -863,7 +863,7 @@ class TestRipper::ParserEvents < Test::Unit::TestCase thru_params = false parse('a {|**x|}', :on_params) {|_, *v| thru_params = true; arg = v} assert_equal true, thru_params - assert_equal [nil, nil, nil, nil, nil, "x", nil], arg + assert_equal [nil, nil, nil, nil, nil, "**x", nil], arg end def test_paren @@ -971,6 +971,15 @@ class TestRipper::ParserEvents < Test::Unit::TestCase assert_equal true, thru_rest_param end + def test_kwrest_param + thru_kwrest = false + parse('def a(**) end', :on_kwrest_param) {|n, val| thru_kwrest = val} + assert_equal nil, thru_kwrest + thru_kwrest = false + parse('def a(**x) end', :on_kwrest_param) {|n, val| thru_kwrest = val} + assert_equal "x", thru_kwrest + end + def test_retry thru_retry = false parse('retry', :on_retry) {thru_retry = true} |