Skip to content

Commit

Permalink
* variable.c (rb_mod_class_variables): return inherited variables
Browse files Browse the repository at this point in the history
  except when the optional argument is set to false.
  [ruby-dev:44034] [Bug ruby#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
  • Loading branch information
shugo committed Jul 19, 2012
1 parent 0e60c71 commit 1f03c90
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 14 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
2 changes: 1 addition & 1 deletion include/ruby/intern.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion object.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
12 changes: 12 additions & 0 deletions test/ruby/test_module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1356,4 +1356,16 @@ def test_prepend_instance_methods_false
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 changes: 71 additions & 12 deletions variable.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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);
}

/*
Expand Down

0 comments on commit 1f03c90

Please sign in to comment.