1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Prohibit setter method names in all kinds of endless methods

Also unwrap NODE_RIPPER to check the method name.
This commit is contained in:
Nobuyoshi Nakada 2020-10-12 00:26:39 +09:00
parent 27b48089e2
commit 4ed0c33d13
No known key found for this signature in database
GPG key ID: 7CD2805BFA3770C6
Notes: git 2020-10-12 01:54:09 +09:00
3 changed files with 66 additions and 10 deletions

19
parse.y
View file

@ -961,6 +961,18 @@ restore_defun(struct parser_params *p, NODE *name)
p->ctxt.in_def = c.ctxt.in_def;
}
static void
endless_method_name(struct parser_params *p, NODE *defn, const YYLTYPE *loc)
{
#ifdef RIPPER
defn = defn->nd_defn;
#endif
ID mid = defn->nd_mid;
if (is_attrset_id(mid)) {
yyerror1(loc, "setter method cannot be defined in an endless method definition");
}
}
#ifndef RIPPER
# define Qnone 0
# define Qnull 0
@ -2477,9 +2489,7 @@ arg : lhs '=' arg_rhs
}
| defn_head f_paren_args '=' arg
{
if (is_attrset_id($<node>1->nd_mid)) {
yyerror1(&@1, "setter method cannot be defined in an endless method definition");
}
endless_method_name(p, $<node>1, &@1);
token_info_drop(p, "def", @1.beg_pos);
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
@ -2490,6 +2500,7 @@ arg : lhs '=' arg_rhs
}
| defn_head f_paren_args '=' arg modifier_rescue arg
{
endless_method_name(p, $<node>1, &@1);
token_info_drop(p, "def", @1.beg_pos);
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
@ -2501,6 +2512,7 @@ arg : lhs '=' arg_rhs
}
| defs_head f_paren_args '=' arg
{
endless_method_name(p, $<node>1, &@1);
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
$$ = set_defun_body(p, $1, $2, $4, &@$);
@ -2512,6 +2524,7 @@ arg : lhs '=' arg_rhs
}
| defs_head f_paren_args '=' arg modifier_rescue arg
{
endless_method_name(p, $<node>1, &@1);
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
$4 = rescued_expr(p, $4, $6, &@4, &@5, &@6);

View file

@ -660,11 +660,30 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
}
assert_equal true, thru_def
assert_equal '[def(foo,[],bodystmt([void()]))]', parse('def foo ;end')
end
thru_def = false
tree = parse('def foo() = 42', :on_def) {thru_def = true}
assert_equal true, thru_def
def test_endless_def
events = %i[on_def on_parse_error]
thru = nil
hook = ->(name, *) {thru[name] = true}
thru = {}
tree = parse('def foo() = 42', events, &hook)
assert_equal({on_def: true}, thru)
assert_equal '[def(foo,[],42)]', tree
thru = {}
tree = parse('def foo() = 42 rescue 0', events, &hook)
assert_equal({on_def: true}, thru)
assert_equal '[def(foo,[],rescue_mod(42,0))]', tree
thru = {}
tree = parse('def foo=() = 42', events, &hook)
assert_equal({on_def: true, on_parse_error: true}, thru)
thru = {}
tree = parse('def foo=() = 42 rescue 0', events, &hook)
assert_equal({on_def: true, on_parse_error: true}, thru)
end
def test_defined
@ -682,11 +701,30 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
thru_parse_error = false
tree = parse('def foo&.bar; end', :on_parse_error) {thru_parse_error = true}
assert_equal(true, thru_parse_error)
end
thru_defs = false
tree = parse('def foo.bar() = 42', :on_defs) {thru_defs = true}
assert_equal true, thru_defs
def test_endless_defs
events = %i[on_defs on_parse_error]
thru = nil
hook = ->(name, *) {thru[name] = true}
thru = {}
tree = parse('def foo.bar() = 42', events, &hook)
assert_equal({on_defs: true}, thru)
assert_equal '[defs(vcall(foo),.,bar,[],42)]', tree
thru = {}
tree = parse('def foo.bar() = 42 rescue 0', events, &hook)
assert_equal({on_defs: true}, thru)
assert_equal '[defs(vcall(foo),.,bar,[],rescue_mod(42,0))]', tree
thru = {}
tree = parse('def foo.bar=() = 42', events, &hook)
assert_equal({on_defs: true, on_parse_error: true}, thru)
thru = {}
tree = parse('def foo.bar=() = 42 rescue 0', events, &hook)
assert_equal({on_defs: true, on_parse_error: true}, thru)
end
def test_do_block

View file

@ -1429,7 +1429,12 @@ eom
end
assert_equal("class ok", k.rescued("ok"))
assert_equal("instance ok", k.new.rescued("ok"))
assert_syntax_error('def foo=() = 42', /setter method cannot be defined in an endless method definition/)
error = /setter method cannot be defined in an endless method definition/
assert_syntax_error('def foo=() = 42', error)
assert_syntax_error('def obj.foo=() = 42', error)
assert_syntax_error('def foo=() = 42 rescue nil', error)
assert_syntax_error('def obj.foo=() = 42 rescue nil', error)
end
def test_methoddef_in_cond