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:
parent
347f3f30d6
commit
140f8b94ce
2 changed files with 35 additions and 4 deletions
31
class.c
31
class.c
|
@ -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();
|
||||
|
|
|
@ -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 }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue