summaryrefslogtreecommitdiff
path: root/class.c
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-02-25 06:01:25 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-02-25 06:01:25 +0000
commit94ec0a64197ab7a0edfb6599074df0a2920607e4 (patch)
tree687082f0a7811e404327e0ce8dac4b1f60621b7c /class.c
parent24bb5756b1e61279c0be437c10210ad26e951ffd (diff)
merge revision(s) 49222,49480,49493: [Backport #10765] [Backport #1010826]
method.h: UNDEFINED_REFINED_METHOD_P * method.h (UNDEFINED_REFINED_METHOD_P): macro to tell if refined original method is defined. * vm_method.c (remove_method): When remove refined method, raise a NameError if the method is not defined in refined class. But if the method is defined in refined class, it should keep refined method and remove original method. Patch by Seiei Higa. [ruby-core:67722] [Bug #10765] * class.c (method_entry_i, class_instance_method_list, rb_obj_singleton_methods): should not include methods of superclasses if recur is false. [ruby-dev:48854] [Bug #10826] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@49738 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'class.c')
-rw-r--r--class.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/class.c b/class.c
index 384037b2b7..9da8fe76a3 100644
--- a/class.c
+++ b/class.c
@@ -986,25 +986,32 @@ ins_methods_pub_i(st_data_t name, st_data_t type, st_data_t ary)
return ins_methods_push((ID)name, (long)type, (VALUE)ary, NOEX_PUBLIC);
}
+struct method_entry_arg {
+ st_table *list;
+ int recur;
+};
+
static int
method_entry_i(st_data_t key, st_data_t value, st_data_t data)
{
const rb_method_entry_t *me = (const rb_method_entry_t *)value;
- st_table *list = (st_table *)data;
+ struct method_entry_arg *arg = (struct method_entry_arg *)data;
long type;
if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
+ VALUE klass = me->klass;
me = rb_resolve_refined_method(Qnil, me, NULL);
if (!me) return ST_CONTINUE;
+ if (!arg->recur && me->klass != klass) return ST_CONTINUE;
}
- if (!st_lookup(list, key, 0)) {
+ if (!st_lookup(arg->list, key, 0)) {
if (UNDEFINED_METHOD_ENTRY_P(me)) {
type = -1; /* none */
}
else {
type = VISI(me->flag);
}
- st_add_direct(list, key, type);
+ st_add_direct(arg->list, key, type);
}
return ST_CONTINUE;
}
@@ -1014,7 +1021,7 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func
{
VALUE ary;
int recur, prepended = 0;
- st_table *list;
+ struct method_entry_arg me_arg;
if (argc == 0) {
recur = TRUE;
@@ -1030,16 +1037,17 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int obj, int (*func
prepended = 1;
}
- list = st_init_numtable();
+ me_arg.list = st_init_numtable();
+ me_arg.recur = recur;
for (; mod; mod = RCLASS_SUPER(mod)) {
- if (RCLASS_M_TBL(mod)) st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)list);
+ if (RCLASS_M_TBL(mod)) st_foreach(RCLASS_M_TBL(mod), method_entry_i, (st_data_t)&me_arg);
if (BUILTIN_TYPE(mod) == T_ICLASS && !prepended) continue;
if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
if (!recur) break;
}
ary = rb_ary_new();
- st_foreach(list, func, ary);
- st_free_table(list);
+ st_foreach(me_arg.list, func, ary);
+ st_free_table(me_arg.list);
return ary;
}
@@ -1251,8 +1259,9 @@ rb_obj_public_methods(int argc, VALUE *argv, VALUE obj)
VALUE
rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
{
- VALUE recur, ary, klass;
- st_table *list;
+ VALUE recur, ary, klass, origin;
+ struct method_entry_arg me_arg;
+ st_table *mtbl;
if (argc == 0) {
recur = Qtrue;
@@ -1261,22 +1270,24 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
rb_scan_args(argc, argv, "01", &recur);
}
klass = CLASS_OF(obj);
- list = st_init_numtable();
+ origin = RCLASS_ORIGIN(klass);
+ me_arg.list = st_init_numtable();
+ me_arg.recur = RTEST(recur);
if (klass && FL_TEST(klass, FL_SINGLETON)) {
- if (RCLASS_M_TBL(klass))
- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list);
+ if ((mtbl = RCLASS_M_TBL(origin)) != 0)
+ st_foreach(mtbl, method_entry_i, (st_data_t)&me_arg);
klass = RCLASS_SUPER(klass);
}
if (RTEST(recur)) {
while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
- if (RCLASS_M_TBL(klass))
- st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list);
+ if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0)
+ st_foreach(mtbl, method_entry_i, (st_data_t)&me_arg);
klass = RCLASS_SUPER(klass);
}
}
ary = rb_ary_new();
- st_foreach(list, ins_methods_i, ary);
- st_free_table(list);
+ st_foreach(me_arg.list, ins_methods_i, ary);
+ st_free_table(me_arg.list);
return ary;
}