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

class.c: refactor class_instance_method_list

* class.c (class_instance_method_list): gather singleton and
  extended methods first separately from ancestors.
  [ruby-core:90872] [Bug #15501]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66764 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2019-01-09 14:04:21 +00:00
parent 347f3f30d6
commit 140f8b94ce
2 changed files with 35 additions and 4 deletions

31
class.c
View file

@ -1174,6 +1174,23 @@ method_entry_i(ID key, VALUE value, void *data)
return ID_TABLE_CONTINUE;
}
static void
add_instance_method_list(VALUE mod, struct method_entry_arg *me_arg)
{
struct rb_id_table *m_tbl = RCLASS_M_TBL(mod);
if (!m_tbl) return;
rb_id_table_foreach(m_tbl, method_entry_i, me_arg);
}
static bool
particular_class_p(VALUE mod)
{
if (!mod) return false;
if (FL_TEST(mod, FL_SINGLETON)) return true;
if (BUILTIN_TYPE(mod) == T_ICLASS) return true;
return false;
}
static VALUE
class_instance_method_list(int argc, const VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t))
{
@ -1183,17 +1200,23 @@ class_instance_method_list(int argc, const VALUE *argv, VALUE mod, int obj, int
if (rb_check_arity(argc, 0, 1)) recur = RTEST(argv[0]);
me_arg.list = st_init_numtable();
me_arg.recur = recur;
if (obj) {
for (; particular_class_p(mod); mod = RCLASS_SUPER(mod)) {
add_instance_method_list(mod, &me_arg);
}
}
if (!recur && RCLASS_ORIGIN(mod) != mod) {
mod = RCLASS_ORIGIN(mod);
prepended = 1;
}
me_arg.list = st_init_numtable();
me_arg.recur = recur;
for (; mod; mod = RCLASS_SUPER(mod)) {
if (RCLASS_M_TBL(mod)) rb_id_table_foreach(RCLASS_M_TBL(mod), method_entry_i, &me_arg);
add_instance_method_list(mod, &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();

View file

@ -227,6 +227,14 @@ class TestObject < Test::Unit::TestCase
assert_equal([:foo], o.methods(false), bug8044)
end
def test_methods_prepend_singleton
c = Class.new(Module) {private def foo; end}
k = c.new
k.singleton_class
c.module_eval {prepend(Module.new)}
assert_equal([:foo], k.private_methods(false))
end
def test_instance_variable_get
o = Object.new
o.instance_eval { @foo = :foo }