mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* variable.c (rb_mod_class_variables): return inherited variables
except when the optional argument is set to false. [ruby-dev:44034] [Bug #4971] * variable.c (rb_mod_constants): fix typo in documentation. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36466 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
0e60c71038
commit
1f03c90dbf
5 changed files with 93 additions and 14 deletions
|
@ -1,3 +1,11 @@
|
|||
Thu Jul 19 15:38:35 2012 Shugo Maeda <shugo@ruby-lang.org>
|
||||
|
||||
* variable.c (rb_mod_class_variables): return inherited variables
|
||||
except when the optional argument is set to false.
|
||||
[ruby-dev:44034] [Bug #4971]
|
||||
|
||||
* variable.c (rb_mod_constants): fix typo in documentation.
|
||||
|
||||
Thu Jul 19 14:30:43 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* internal.h: move mark function declarations that should be private.
|
||||
|
|
|
@ -886,7 +886,7 @@ VALUE rb_cvar_get(VALUE, ID);
|
|||
void rb_cv_set(VALUE, const char*, VALUE);
|
||||
VALUE rb_cv_get(VALUE, const char*);
|
||||
void rb_define_class_variable(VALUE, const char*, VALUE);
|
||||
VALUE rb_mod_class_variables(VALUE);
|
||||
VALUE rb_mod_class_variables(int, VALUE*, VALUE);
|
||||
VALUE rb_mod_remove_cvar(VALUE, VALUE);
|
||||
|
||||
ID rb_frame_callee(void);
|
||||
|
|
2
object.c
2
object.c
|
@ -2979,7 +2979,7 @@ Init_Object(void)
|
|||
rb_define_method(rb_cModule, "const_missing",
|
||||
rb_mod_const_missing, 1); /* in variable.c */
|
||||
rb_define_method(rb_cModule, "class_variables",
|
||||
rb_mod_class_variables, 0); /* in variable.c */
|
||||
rb_mod_class_variables, -1); /* in variable.c */
|
||||
rb_define_method(rb_cModule, "remove_class_variable",
|
||||
rb_mod_remove_cvar, 1); /* in variable.c */
|
||||
rb_define_method(rb_cModule, "class_variable_get", rb_mod_cvar_get, 1);
|
||||
|
|
|
@ -1356,4 +1356,16 @@ class TestModule < Test::Unit::TestCase
|
|||
assert_equal([:m1], Class.new{ prepend Module.new; def m1; end }.instance_methods(false), bug6660)
|
||||
assert_equal([:m1], Class.new(Class.new{def m2;end}){ prepend Module.new; def m1; end }.instance_methods(false), bug6660)
|
||||
end
|
||||
|
||||
def test_class_variables
|
||||
m = Module.new
|
||||
m.class_variable_set(:@@foo, 1)
|
||||
m2 = Module.new
|
||||
m2.send(:include, m)
|
||||
m2.class_variable_set(:@@bar, 2)
|
||||
assert_equal([:@@foo], m.class_variables)
|
||||
assert_equal([:@@bar, :@@foo], m2.class_variables)
|
||||
assert_equal([:@@bar, :@@foo], m2.class_variables(true))
|
||||
assert_equal([:@@bar], m2.class_variables(false))
|
||||
end
|
||||
end
|
||||
|
|
83
variable.c
83
variable.c
|
@ -1939,7 +1939,7 @@ rb_const_list(void *data)
|
|||
*
|
||||
* Returns an array of the names of the constants accessible in
|
||||
* <i>mod</i>. This includes the names of constants in any included
|
||||
* modules (example at start of section), unless the <i>all</i>
|
||||
* modules (example at start of section), unless the <i>inherit</i>
|
||||
* parameter is set to <code>false</code>.
|
||||
*
|
||||
* IO.constants.include?(:SYNC) #=> true
|
||||
|
@ -2323,22 +2323,71 @@ static int
|
|||
cv_i(st_data_t k, st_data_t v, st_data_t a)
|
||||
{
|
||||
ID key = (ID)k;
|
||||
VALUE ary = (VALUE)a;
|
||||
st_table *tbl = (st_table *)a;
|
||||
|
||||
if (rb_is_class_id(key)) {
|
||||
VALUE kval = ID2SYM(key);
|
||||
if (!rb_ary_includes(ary, kval)) {
|
||||
rb_ary_push(ary, kval);
|
||||
if (!st_lookup(tbl, (st_data_t)key, 0)) {
|
||||
st_insert(tbl, (st_data_t)key, 0);
|
||||
}
|
||||
}
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
static void*
|
||||
mod_cvar_at(VALUE mod, void *data)
|
||||
{
|
||||
st_table *tbl = data;
|
||||
if (!tbl) {
|
||||
tbl = st_init_numtable();
|
||||
}
|
||||
if (RCLASS_IV_TBL(mod)) {
|
||||
st_foreach_safe(RCLASS_IV_TBL(mod), cv_i, (st_data_t)tbl);
|
||||
}
|
||||
return tbl;
|
||||
}
|
||||
|
||||
static void*
|
||||
mod_cvar_of(VALUE mod, void *data)
|
||||
{
|
||||
VALUE tmp = mod;
|
||||
for (;;) {
|
||||
data = mod_cvar_at(tmp, data);
|
||||
tmp = RCLASS_SUPER(tmp);
|
||||
if (!tmp) break;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static int
|
||||
cv_list_i(st_data_t key, st_data_t value, VALUE ary)
|
||||
{
|
||||
ID sym = (ID)key;
|
||||
rb_ary_push(ary, ID2SYM(sym));
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
cvar_list(void *data)
|
||||
{
|
||||
st_table *tbl = data;
|
||||
VALUE ary;
|
||||
|
||||
if (!tbl) return rb_ary_new2(0);
|
||||
ary = rb_ary_new2(tbl->num_entries);
|
||||
st_foreach_safe(tbl, cv_list_i, ary);
|
||||
st_free_table(tbl);
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* mod.class_variables -> array
|
||||
* mod.class_variables(inherit=true) -> array
|
||||
*
|
||||
* Returns an array of the names of class variables in <i>mod</i>.
|
||||
* This includes the names of class variables in any included
|
||||
* modules, unless the <i>inherit</i> parameter is set to
|
||||
* <code>false</code>.
|
||||
*
|
||||
* class One
|
||||
* @@var1 = 1
|
||||
|
@ -2347,18 +2396,28 @@ cv_i(st_data_t k, st_data_t v, st_data_t a)
|
|||
* @@var2 = 2
|
||||
* end
|
||||
* One.class_variables #=> [:@@var1]
|
||||
* Two.class_variables #=> [:@@var2]
|
||||
* Two.class_variables #=> [:@@var2, :@@var1]
|
||||
*/
|
||||
|
||||
VALUE
|
||||
rb_mod_class_variables(VALUE obj)
|
||||
rb_mod_class_variables(int argc, VALUE *argv, VALUE mod)
|
||||
{
|
||||
VALUE ary = rb_ary_new();
|
||||
VALUE inherit;
|
||||
st_table *tbl;
|
||||
|
||||
if (RCLASS_IV_TBL(obj)) {
|
||||
st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, (st_data_t)ary);
|
||||
if (argc == 0) {
|
||||
inherit = Qtrue;
|
||||
}
|
||||
return ary;
|
||||
else {
|
||||
rb_scan_args(argc, argv, "01", &inherit);
|
||||
}
|
||||
if (RTEST(inherit)) {
|
||||
tbl = mod_cvar_of(mod, 0);
|
||||
}
|
||||
else {
|
||||
tbl = mod_cvar_at(mod, 0);
|
||||
}
|
||||
return cvar_list(tbl);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue