ruby-changes:24415
From: shugo <ko1@a...>
Date: Thu, 19 Jul 2012 15:42:00 +0900 (JST)
Subject: [ruby-changes:24415] shugo:r36466 (trunk): * variable.c (rb_mod_class_variables): return inherited variables
shugo 2012-07-19 15:41:47 +0900 (Thu, 19 Jul 2012) New Revision: 36466 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=36466 Log: * 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. Modified files: trunk/ChangeLog trunk/include/ruby/intern.h trunk/object.c trunk/test/ruby/test_module.rb trunk/variable.c Index: include/ruby/intern.h =================================================================== --- include/ruby/intern.h (revision 36465) +++ include/ruby/intern.h (revision 36466) @@ -886,7 +886,7 @@ 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); Index: ChangeLog =================================================================== --- ChangeLog (revision 36465) +++ ChangeLog (revision 36466) @@ -1,3 +1,11 @@ +Thu Jul 19 15:38:35 2012 Shugo Maeda <shugo@r...> + + * 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@r...> * internal.h: move mark function declarations that should be private. Index: variable.c =================================================================== --- variable.c (revision 36465) +++ variable.c (revision 36466) @@ -1939,7 +1939,7 @@ * * 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 @@ 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 @@ * @@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); } /* Index: object.c =================================================================== --- object.c (revision 36465) +++ object.c (revision 36466) @@ -2979,7 +2979,7 @@ 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); Index: test/ruby/test_module.rb =================================================================== --- test/ruby/test_module.rb (revision 36465) +++ test/ruby/test_module.rb (revision 36466) @@ -1356,4 +1356,16 @@ 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 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/