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

ruby-changes:64250

From: Rados=C5=82aw <ko1@a...>
Date: Fri, 18 Dec 2020 02:46:25 +0900 (JST)
Subject: [ruby-changes:64250] 81739ad4fd (master): Better cooperation between public/protected/private with attr* and alias_method

https://git.ruby-lang.org/ruby.git/commit/?id=81739ad4fd

From 81739ad4fdfcc86a769056fec352f27c686fba1b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rados=C5=82aw=20Bu=C5=82at?= <radek.bulat@g...>
Date: Mon, 9 Nov 2020 11:25:11 +0100
Subject: Better cooperation between public/protected/private with attr* and
 alias_method


diff --git a/NEWS.md b/NEWS.md
index 2e20e8d..613976b 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -249,6 +249,16 @@ Outstanding ones only. https://github.com/ruby/ruby/blob/trunk/NEWS.md#L249
         p C.ancestors #=> [C, M1, M2, Object, Kernel, BasicObject]
         ```
 
+    * Module#public, Module#protected and Module#private methods now accept single
+      array argument with a list of method names. [[Feature #17314]]
+
+    * Module#attr_accessor, Module#attr_reader, Module#attr_writer and Module#attr
+      methods now return array of defined methods names as symbols.
+      [[Feature #17314]]
+
+    * Module#alias_method now returns the defined alias as symbol.
+      [[Feature #17314]]
+
 * Mutex
 
     * `Mutex` is now acquired per-`Fiber` instead of per-`Thread`. This change
@@ -691,3 +701,4 @@ end https://github.com/ruby/ruby/blob/trunk/NEWS.md#L701
 [Feature #17371]: https://bugs.ruby-lang.org/issues/17371
 [GH-2991]:        https://github.com/ruby/ruby/pull/2991
 [Bug #17030]:     https://bugs.ruby-lang.org/issues/17030
+[Feature #17314]: https://bugs.ruby-lang.org/issues/17314
diff --git a/object.c b/object.c
index 552b10b..4fe6b02 100644
--- a/object.c
+++ b/object.c
@@ -2255,37 +2255,42 @@ id_for_attr(VALUE obj, VALUE name) https://github.com/ruby/ruby/blob/trunk/object.c#L2255
 
 /*
  *  call-seq:
- *     attr_reader(symbol, ...)  -> nil
- *     attr(symbol, ...)         -> nil
- *     attr_reader(string, ...)  -> nil
- *     attr(string, ...)         -> nil
+ *     attr_reader(symbol, ...)  -> array
+ *     attr(symbol, ...)         -> array
+ *     attr_reader(string, ...)  -> array
+ *     attr(string, ...)         -> array
  *
  *  Creates instance variables and corresponding methods that return the
  *  value of each instance variable. Equivalent to calling
  *  ``<code>attr</code><i>:name</i>'' on each name in turn.
  *  String arguments are converted to symbols.
+ *  Returns an array of defined methods names as symbols.
  */
 
 static VALUE
 rb_mod_attr_reader(int argc, VALUE *argv, VALUE klass)
 {
     int i;
+    VALUE names = rb_ary_new2(argc);
 
     for (i=0; i<argc; i++) {
-	rb_attr(klass, id_for_attr(klass, argv[i]), TRUE, FALSE, TRUE);
+	ID id = id_for_attr(klass, argv[i]);
+	rb_attr(klass, id, TRUE, FALSE, TRUE);
+	rb_ary_push(names, ID2SYM(id));
     }
-    return Qnil;
+    return names;
 }
 
 /**
  *  call-seq:
- *    attr(name, ...) -> nil
- *    attr(name, true) -> nil
- *    attr(name, false) -> nil
+ *    attr(name, ...) -> array
+ *    attr(name, true) -> array
+ *    attr(name, false) -> array
  *
  *  The first form is equivalent to #attr_reader.
  *  The second form is equivalent to <code>attr_accessor(name)</code> but deprecated.
  *  The last form is equivalent to <code>attr_reader(name)</code> but deprecated.
+ *  Returns an array of defined methods names as symbols.
  *--
  * \private
  * \todo can be static?
@@ -2295,47 +2300,57 @@ VALUE https://github.com/ruby/ruby/blob/trunk/object.c#L2300
 rb_mod_attr(int argc, VALUE *argv, VALUE klass)
 {
     if (argc == 2 && (argv[1] == Qtrue || argv[1] == Qfalse)) {
+	ID id = id_for_attr(klass, argv[0]);
+	VALUE names = rb_ary_new();
+
 	rb_warning("optional boolean argument is obsoleted");
-	rb_attr(klass, id_for_attr(klass, argv[0]), 1, RTEST(argv[1]), TRUE);
-	return Qnil;
+	rb_attr(klass, id, 1, RTEST(argv[1]), TRUE);
+	rb_ary_push(names, ID2SYM(id));
+	if (argv[1] == Qtrue) rb_ary_push(names, rb_str_intern(rb_sprintf("%"PRIsVALUE"=", ID2SYM(id))));
+	return names;
     }
     return rb_mod_attr_reader(argc, argv, klass);
 }
 
 /*
  *  call-seq:
- *      attr_writer(symbol, ...)    -> nil
- *      attr_writer(string, ...)    -> nil
+ *      attr_writer(symbol, ...)    -> array
+ *      attr_writer(string, ...)    -> array
  *
  *  Creates an accessor method to allow assignment to the attribute
  *  <i>symbol</i><code>.id2name</code>.
  *  String arguments are converted to symbols.
+ *  Returns an array of defined methods names as symbols.
  */
 
 static VALUE
 rb_mod_attr_writer(int argc, VALUE *argv, VALUE klass)
 {
     int i;
+    VALUE names = rb_ary_new2(argc);
 
     for (i=0; i<argc; i++) {
-	rb_attr(klass, id_for_attr(klass, argv[i]), FALSE, TRUE, TRUE);
+	ID id = id_for_attr(klass, argv[i]);
+	rb_attr(klass, id, FALSE, TRUE, TRUE);
+	rb_ary_push(names, rb_str_intern(rb_sprintf("%"PRIsVALUE"=", ID2SYM(id))));
     }
-    return Qnil;
+    return names;
 }
 
 /*
  *  call-seq:
- *     attr_accessor(symbol, ...)    -> nil
- *     attr_accessor(string, ...)    -> nil
+ *     attr_accessor(symbol, ...)    -> array
+ *     attr_accessor(string, ...)    -> array
  *
  *  Defines a named attribute for this module, where the name is
  *  <i>symbol.</i><code>id2name</code>, creating an instance variable
  *  (<code>@name</code>) and a corresponding access method to read it.
  *  Also creates a method called <code>name=</code> to set the attribute.
  *  String arguments are converted to symbols.
+ *  Returns an array of defined methods names as symbols.
  *
  *     module Mod
- *       attr_accessor(:one, :two)
+ *       attr_accessor(:one, :two) #=> [:one, :one=, :two, :two=]
  *     end
  *     Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]
  */
@@ -2344,11 +2359,17 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/object.c#L2359
 rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass)
 {
     int i;
+    VALUE names = rb_ary_new2(argc * 2);
 
     for (i=0; i<argc; i++) {
-	rb_attr(klass, id_for_attr(klass, argv[i]), TRUE, TRUE, TRUE);
+	ID id = id_for_attr(klass, argv[i]);
+	VALUE idv = ID2SYM(id);
+
+	rb_attr(klass, id, TRUE, TRUE, TRUE);
+	rb_ary_push(names, idv);
+	rb_ary_push(names, rb_str_intern(rb_sprintf("%"PRIsVALUE"=", idv)));
     }
-    return Qnil;
+    return names;
 }
 
 /*
diff --git a/process.c b/process.c
index dee565e..0b2fdeb 100644
--- a/process.c
+++ b/process.c
@@ -2075,12 +2075,11 @@ check_exec_redirect1(VALUE ary, VALUE key, VALUE param) https://github.com/ruby/ruby/blob/trunk/process.c#L2075
         rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
     }
     else {
-        int i, n=0;
+        int i;
         for (i = 0 ; i < RARRAY_LEN(key); i++) {
             VALUE v = RARRAY_AREF(key, i);
             VALUE fd = check_exec_redirect_fd(v, !NIL_P(param));
             rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
-            n++;
         }
     }
     return ary;
diff --git a/spec/ruby/core/main/fixtures/classes.rb b/spec/ruby/core/main/fixtures/classes.rb
index 6aba948..757cee4 100644
--- a/spec/ruby/core/main/fixtures/classes.rb
+++ b/spec/ruby/core/main/fixtures/classes.rb
@@ -13,6 +13,14 @@ def main_public_method https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/main/fixtures/classes.rb#L13
 end
 public :main_public_method
 
+def main_public_method2
+end
+public :main_public_method2
+
 def main_private_method
 end
 private :main_private_method
+
+def main_private_method2
+end
+private :main_private_method2
diff --git a/spec/ruby/core/main/private_spec.rb b/spec/ruby/core/main/private_spec.rb
index e34e0c7..78c5d28 100644
--- a/spec/ruby/core/main/private_spec.rb
+++ b/spec/ruby/core/main/private_spec.rb
@@ -4,20 +4,41 @@ require_relative 'fixtures/classes' https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/main/private_spec.rb#L4
 describe "main#private" do
   after :each do
     Object.send(:public, :main_public_method)
+    Object.send(:public, :main_public_method2)
   end
 
-  it "sets the visibility of the given method to private" do
-    eval "private :main_public_method", TOPLEVEL_BINDING
-    Object.should have_private_method(:main_public_method)
+  context "when single argument is passed and it is not an array" do
+    it "sets the visibility of the given methods to private" do
+      eval "private :main_public_method", TOPLEVEL_BINDING
+      Object.should have_private_method(:main_public_method)
+    end
+  end
+
+  context "when multiple arguments are passed" do
+    it "sets the visibility of the given methods to private" do
+      eval "private :main_public_method, :main_public_method2", TOPLEVEL_BINDING
+      Object.should have_private_method(:main_public_method)
+      Object.should have_private_method(:main_public_method2)
+    end
+  end
+
+  ruby_version_is "3.0" do
+    context "when single argument is passed and is an array" do
+      it "sets the visibility of the given methods to private" do
+        eval "private [:main_public_method, :main_public_method2]", TOPLEVEL_BINDING
+        Object.should have_private_method(:main_public_method)
+        Object.should have_private_method(:main_public_method2)
+      end
+    end
   end
 
   it "returns Object" do
     eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object)
   end
 
-  it "raises a NameError when given an undefined name" do
+  it "raises a NameError when at least one of given method names is undefined" do
     -> do
-      eval "private :main_undefined_method", TOPLEVEL_BINDING
+      eval "private :main_public_method, :main_undefined_method", TOPLEVEL_BINDING
     end.should raise_error(NameError)
   end
 end
diff --git a/spec/ruby/core/main/public_spec.rb b/spec/ruby/core/main/public_spec.rb
index afe25c7..bfc27a9e 100644
--- a/spec/ruby/core/main/public_spec.rb
+++ b/spec/ruby/core/main/public_spec.rb
@@ -4,11 +4,32 @@ require_relative 'fixtures/classes' https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/main/public_spec.rb#L4
 describe "main#public" do
   after :each do
     Object.send(:private, :main_private_method)
+    Object.send(:private, :main_private_method2)
   end
 
-  it "sets the visibility of the given method to public" do
-    eval "public :main_private_metho (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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