[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]