Fix arg_forward without parentheses [Bug #18267]
This commit is contained in:
parent
3a6b79d0c0
commit
aa7c4c37d7
Notes:
git
2021-12-15 07:01:46 +09:00
36
parse.y
36
parse.y
@ -64,6 +64,7 @@ enum shareability {
|
|||||||
struct lex_context {
|
struct lex_context {
|
||||||
unsigned int in_defined: 1;
|
unsigned int in_defined: 1;
|
||||||
unsigned int in_kwarg: 1;
|
unsigned int in_kwarg: 1;
|
||||||
|
unsigned int in_argdef: 1;
|
||||||
unsigned int in_def: 1;
|
unsigned int in_def: 1;
|
||||||
unsigned int in_class: 1;
|
unsigned int in_class: 1;
|
||||||
BITFIELD(enum shareability, shareable_constant_value, 2);
|
BITFIELD(enum shareability, shareable_constant_value, 2);
|
||||||
@ -1817,7 +1818,12 @@ defn_head : k_def def_name
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
defs_head : k_def singleton dot_or_colon {SET_LEX_STATE(EXPR_FNAME);} def_name
|
defs_head : k_def singleton dot_or_colon
|
||||||
|
{
|
||||||
|
SET_LEX_STATE(EXPR_FNAME);
|
||||||
|
p->ctxt.in_argdef = 1;
|
||||||
|
}
|
||||||
|
def_name
|
||||||
{
|
{
|
||||||
SET_LEX_STATE(EXPR_ENDFN|EXPR_LABEL); /* force for args */
|
SET_LEX_STATE(EXPR_ENDFN|EXPR_LABEL); /* force for args */
|
||||||
$$ = $5;
|
$$ = $5;
|
||||||
@ -3396,6 +3402,7 @@ k_module : keyword_module
|
|||||||
k_def : keyword_def
|
k_def : keyword_def
|
||||||
{
|
{
|
||||||
token_info_push(p, "def", &@$);
|
token_info_push(p, "def", &@$);
|
||||||
|
p->ctxt.in_argdef = 1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -3591,6 +3598,8 @@ f_any_kwrest : f_kwrest
|
|||||||
| f_no_kwarg {$$ = ID2VAL(idNil);}
|
| f_no_kwarg {$$ = ID2VAL(idNil);}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
f_eq : {p->ctxt.in_argdef = 0;} '=';
|
||||||
|
|
||||||
block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
|
block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
|
||||||
{
|
{
|
||||||
$$ = new_args_tail(p, $1, $3, $4, &@3);
|
$$ = new_args_tail(p, $1, $3, $4, &@3);
|
||||||
@ -3703,6 +3712,7 @@ block_param_def : '|' opt_bv_decl '|'
|
|||||||
{
|
{
|
||||||
p->cur_arg = 0;
|
p->cur_arg = 0;
|
||||||
p->max_numparam = ORDINAL_PARAM;
|
p->max_numparam = ORDINAL_PARAM;
|
||||||
|
p->ctxt.in_argdef = 0;
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
/*% %*/
|
/*% %*/
|
||||||
@ -3712,6 +3722,7 @@ block_param_def : '|' opt_bv_decl '|'
|
|||||||
{
|
{
|
||||||
p->cur_arg = 0;
|
p->cur_arg = 0;
|
||||||
p->max_numparam = ORDINAL_PARAM;
|
p->max_numparam = ORDINAL_PARAM;
|
||||||
|
p->ctxt.in_argdef = 0;
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
/*% %*/
|
/*% %*/
|
||||||
@ -3792,6 +3803,7 @@ lambda : tLAMBDA
|
|||||||
|
|
||||||
f_larglist : '(' f_args opt_bv_decl ')'
|
f_larglist : '(' f_args opt_bv_decl ')'
|
||||||
{
|
{
|
||||||
|
p->ctxt.in_argdef = 0;
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
p->max_numparam = ORDINAL_PARAM;
|
p->max_numparam = ORDINAL_PARAM;
|
||||||
@ -3800,6 +3812,7 @@ f_larglist : '(' f_args opt_bv_decl ')'
|
|||||||
}
|
}
|
||||||
| f_args
|
| f_args
|
||||||
{
|
{
|
||||||
|
p->ctxt.in_argdef = 0;
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
if (!args_info_empty_p($1->nd_ainfo))
|
if (!args_info_empty_p($1->nd_ainfo))
|
||||||
p->max_numparam = ORDINAL_PARAM;
|
p->max_numparam = ORDINAL_PARAM;
|
||||||
@ -5122,6 +5135,7 @@ superclass : '<'
|
|||||||
f_opt_paren_args: f_paren_args
|
f_opt_paren_args: f_paren_args
|
||||||
| none
|
| none
|
||||||
{
|
{
|
||||||
|
p->ctxt.in_argdef = 0;
|
||||||
$$ = new_args_tail(p, Qnone, Qnone, Qnone, &@0);
|
$$ = new_args_tail(p, Qnone, Qnone, Qnone, &@0);
|
||||||
$$ = new_args(p, Qnone, Qnone, Qnone, Qnone, $$, &@0);
|
$$ = new_args(p, Qnone, Qnone, Qnone, Qnone, $$, &@0);
|
||||||
}
|
}
|
||||||
@ -5135,6 +5149,7 @@ f_paren_args : '(' f_args rparen
|
|||||||
/*% ripper: paren!($2) %*/
|
/*% ripper: paren!($2) %*/
|
||||||
SET_LEX_STATE(EXPR_BEG);
|
SET_LEX_STATE(EXPR_BEG);
|
||||||
p->command_start = TRUE;
|
p->command_start = TRUE;
|
||||||
|
p->ctxt.in_argdef = 0;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -5142,11 +5157,13 @@ f_arglist : f_paren_args
|
|||||||
| {
|
| {
|
||||||
$<ctxt>$ = p->ctxt;
|
$<ctxt>$ = p->ctxt;
|
||||||
p->ctxt.in_kwarg = 1;
|
p->ctxt.in_kwarg = 1;
|
||||||
|
p->ctxt.in_argdef = 1;
|
||||||
SET_LEX_STATE(p->lex.state|EXPR_LABEL); /* force for args */
|
SET_LEX_STATE(p->lex.state|EXPR_LABEL); /* force for args */
|
||||||
}
|
}
|
||||||
f_args term
|
f_args term
|
||||||
{
|
{
|
||||||
p->ctxt.in_kwarg = $<ctxt>1.in_kwarg;
|
p->ctxt.in_kwarg = $<ctxt>1.in_kwarg;
|
||||||
|
p->ctxt.in_argdef = 0;
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
SET_LEX_STATE(EXPR_BEG);
|
SET_LEX_STATE(EXPR_BEG);
|
||||||
p->command_start = TRUE;
|
p->command_start = TRUE;
|
||||||
@ -5363,6 +5380,7 @@ f_label : tLABEL
|
|||||||
arg_var(p, formal_argument(p, $1));
|
arg_var(p, formal_argument(p, $1));
|
||||||
p->cur_arg = get_id($1);
|
p->cur_arg = get_id($1);
|
||||||
p->max_numparam = ORDINAL_PARAM;
|
p->max_numparam = ORDINAL_PARAM;
|
||||||
|
p->ctxt.in_argdef = 0;
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -5370,6 +5388,7 @@ f_label : tLABEL
|
|||||||
f_kw : f_label arg_value
|
f_kw : f_label arg_value
|
||||||
{
|
{
|
||||||
p->cur_arg = 0;
|
p->cur_arg = 0;
|
||||||
|
p->ctxt.in_argdef = 1;
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
$$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$);
|
$$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$);
|
||||||
/*% %*/
|
/*% %*/
|
||||||
@ -5378,6 +5397,7 @@ f_kw : f_label arg_value
|
|||||||
| f_label
|
| f_label
|
||||||
{
|
{
|
||||||
p->cur_arg = 0;
|
p->cur_arg = 0;
|
||||||
|
p->ctxt.in_argdef = 1;
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
$$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$);
|
$$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$);
|
||||||
/*% %*/
|
/*% %*/
|
||||||
@ -5387,6 +5407,7 @@ f_kw : f_label arg_value
|
|||||||
|
|
||||||
f_block_kw : f_label primary_value
|
f_block_kw : f_label primary_value
|
||||||
{
|
{
|
||||||
|
p->ctxt.in_argdef = 1;
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
$$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$);
|
$$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$);
|
||||||
/*% %*/
|
/*% %*/
|
||||||
@ -5394,6 +5415,7 @@ f_block_kw : f_label primary_value
|
|||||||
}
|
}
|
||||||
| f_label
|
| f_label
|
||||||
{
|
{
|
||||||
|
p->ctxt.in_argdef = 1;
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
$$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$);
|
$$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$);
|
||||||
/*% %*/
|
/*% %*/
|
||||||
@ -5464,9 +5486,10 @@ f_kwrest : kwrest_mark tIDENTIFIER
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
f_opt : f_arg_asgn '=' arg_value
|
f_opt : f_arg_asgn f_eq arg_value
|
||||||
{
|
{
|
||||||
p->cur_arg = 0;
|
p->cur_arg = 0;
|
||||||
|
p->ctxt.in_argdef = 1;
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
$$ = NEW_OPT_ARG(0, assignable(p, $1, $3, &@$), &@$);
|
$$ = NEW_OPT_ARG(0, assignable(p, $1, $3, &@$), &@$);
|
||||||
/*% %*/
|
/*% %*/
|
||||||
@ -5474,9 +5497,10 @@ f_opt : f_arg_asgn '=' arg_value
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
f_block_opt : f_arg_asgn '=' primary_value
|
f_block_opt : f_arg_asgn f_eq primary_value
|
||||||
{
|
{
|
||||||
p->cur_arg = 0;
|
p->cur_arg = 0;
|
||||||
|
p->ctxt.in_argdef = 1;
|
||||||
/*%%%*/
|
/*%%%*/
|
||||||
$$ = NEW_OPT_ARG(0, assignable(p, $1, $3, &@$), &@$);
|
$$ = NEW_OPT_ARG(0, assignable(p, $1, $3, &@$), &@$);
|
||||||
/*% %*/
|
/*% %*/
|
||||||
@ -9659,13 +9683,11 @@ parser_yylex(struct parser_params *p)
|
|||||||
SET_LEX_STATE(EXPR_BEG);
|
SET_LEX_STATE(EXPR_BEG);
|
||||||
if ((c = nextc(p)) == '.') {
|
if ((c = nextc(p)) == '.') {
|
||||||
if ((c = nextc(p)) == '.') {
|
if ((c = nextc(p)) == '.') {
|
||||||
if (p->lex.paren_nest == 0 && looking_at_eol_p(p)) {
|
if (p->ctxt.in_argdef) {
|
||||||
if (p->ctxt.in_argdef || /* def foo a, ... */
|
|
||||||
IS_lex_state_for(last_state, EXPR_ENDFN) || /* def foo ... */
|
|
||||||
0) {
|
|
||||||
SET_LEX_STATE(EXPR_ENDARG);
|
SET_LEX_STATE(EXPR_ENDARG);
|
||||||
return tBDOT3;
|
return tBDOT3;
|
||||||
}
|
}
|
||||||
|
if (p->lex.paren_nest == 0 && looking_at_eol_p(p)) {
|
||||||
rb_warn0("... at EOL, should be parenthesized?");
|
rb_warn0("... at EOL, should be parenthesized?");
|
||||||
}
|
}
|
||||||
else if (p->lex.lpar_beg >= 0 && p->lex.lpar_beg+1 == p->lex.paren_nest) {
|
else if (p->lex.lpar_beg >= 0 && p->lex.lpar_beg+1 == p->lex.paren_nest) {
|
||||||
|
@ -1587,7 +1587,15 @@ eom
|
|||||||
def test_argument_forwarding
|
def test_argument_forwarding
|
||||||
assert_valid_syntax('def foo(...) bar(...) end')
|
assert_valid_syntax('def foo(...) bar(...) end')
|
||||||
assert_valid_syntax('def foo(...) end')
|
assert_valid_syntax('def foo(...) end')
|
||||||
|
assert_valid_syntax('def foo(a, ...) bar(...) end')
|
||||||
assert_valid_syntax("def foo ...\n bar(...)\nend")
|
assert_valid_syntax("def foo ...\n bar(...)\nend")
|
||||||
|
assert_valid_syntax("def foo a, ...\n bar(...)\nend")
|
||||||
|
assert_valid_syntax("def foo b = 1, ...\n bar(...)\nend")
|
||||||
|
assert_valid_syntax("def foo ...; bar(...); end")
|
||||||
|
assert_valid_syntax("def foo a, ...; bar(...); end")
|
||||||
|
assert_valid_syntax("def foo b = 1, ...; bar(...); end")
|
||||||
|
assert_valid_syntax("(def foo ...\n bar(...)\nend)")
|
||||||
|
assert_valid_syntax("(def foo ...; bar(...); end)")
|
||||||
assert_valid_syntax('def ==(...) end')
|
assert_valid_syntax('def ==(...) end')
|
||||||
assert_valid_syntax('def [](...) end')
|
assert_valid_syntax('def [](...) end')
|
||||||
assert_valid_syntax('def nil(...) end')
|
assert_valid_syntax('def nil(...) end')
|
||||||
@ -1618,8 +1626,10 @@ eom
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
obj4 = obj1.clone
|
obj4 = obj1.clone
|
||||||
|
obj5 = obj1.clone
|
||||||
obj1.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__)
|
obj1.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__)
|
||||||
obj4.instance_eval("def foo ...\n bar(...)\n""end", __FILE__, __LINE__)
|
obj4.instance_eval("def foo ...\n bar(...)\n""end", __FILE__, __LINE__)
|
||||||
|
obj5.instance_eval("def foo ...; bar(...); end", __FILE__, __LINE__)
|
||||||
|
|
||||||
klass = Class.new {
|
klass = Class.new {
|
||||||
def foo(*args, **kws, &block)
|
def foo(*args, **kws, &block)
|
||||||
@ -1648,7 +1658,7 @@ eom
|
|||||||
end
|
end
|
||||||
obj3.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__)
|
obj3.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__)
|
||||||
|
|
||||||
[obj1, obj2, obj3, obj4].each do |obj|
|
[obj1, obj2, obj3, obj4, obj5].each do |obj|
|
||||||
assert_warning('') {
|
assert_warning('') {
|
||||||
assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5) {|*x| x})
|
assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5) {|*x| x})
|
||||||
}
|
}
|
||||||
@ -1791,6 +1801,19 @@ eom
|
|||||||
assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1)
|
assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1)
|
||||||
assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1)
|
assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1)
|
||||||
assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]}
|
assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]}
|
||||||
|
|
||||||
|
obj.singleton_class.send(:remove_method, :foo)
|
||||||
|
obj.instance_eval("def foo a, ...; bar(a, ...); end", __FILE__, __LINE__)
|
||||||
|
assert_equal [[4], {}], obj.foo(4)
|
||||||
|
assert_equal [[4, 2], {}], obj.foo(4, 2)
|
||||||
|
assert_equal [[4, 2, 3], {}], obj.foo(4, 2, 3)
|
||||||
|
assert_equal [[4], {a: 1}], obj.foo(4, a: 1)
|
||||||
|
assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1)
|
||||||
|
assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1)
|
||||||
|
assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]}
|
||||||
|
|
||||||
|
exp = eval("-> (a: nil) {a...1}")
|
||||||
|
assert_equal 0...1, exp.call(a: 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_cdhash
|
def test_cdhash
|
||||||
|
Loading…
x
Reference in New Issue
Block a user