Revert "Better cooperation between public/protected/private with attr* and alias_method"

This reverts commit 81739ad4fdfcc86a769056fec352f27c686fba1b.
This commit is contained in:
Yusuke Endoh 2020-12-18 14:12:42 +09:00
parent 41c208d4a4
commit 982443e6e3
13 changed files with 42 additions and 255 deletions

10
NEWS.md
View File

@ -249,16 +249,6 @@ Outstanding ones only.
p C.ancestors #=> [C, M1, M2, Object, Kernel, BasicObject] 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
* `Mutex` is now acquired per-`Fiber` instead of per-`Thread`. This change * `Mutex` is now acquired per-`Fiber` instead of per-`Thread`. This change

View File

@ -2255,42 +2255,37 @@ id_for_attr(VALUE obj, VALUE name)
/* /*
* call-seq: * call-seq:
* attr_reader(symbol, ...) -> array * attr_reader(symbol, ...) -> nil
* attr(symbol, ...) -> array * attr(symbol, ...) -> nil
* attr_reader(string, ...) -> array * attr_reader(string, ...) -> nil
* attr(string, ...) -> array * attr(string, ...) -> nil
* *
* Creates instance variables and corresponding methods that return the * Creates instance variables and corresponding methods that return the
* value of each instance variable. Equivalent to calling * value of each instance variable. Equivalent to calling
* ``<code>attr</code><i>:name</i>'' on each name in turn. * ``<code>attr</code><i>:name</i>'' on each name in turn.
* String arguments are converted to symbols. * String arguments are converted to symbols.
* Returns an array of defined methods names as symbols.
*/ */
static VALUE static VALUE
rb_mod_attr_reader(int argc, VALUE *argv, VALUE klass) rb_mod_attr_reader(int argc, VALUE *argv, VALUE klass)
{ {
int i; int i;
VALUE names = rb_ary_new2(argc);
for (i=0; i<argc; i++) { for (i=0; i<argc; i++) {
ID id = id_for_attr(klass, argv[i]); rb_attr(klass, id_for_attr(klass, argv[i]), TRUE, FALSE, TRUE);
rb_attr(klass, id, TRUE, FALSE, TRUE);
rb_ary_push(names, ID2SYM(id));
} }
return names; return Qnil;
} }
/** /**
* call-seq: * call-seq:
* attr(name, ...) -> array * attr(name, ...) -> nil
* attr(name, true) -> array * attr(name, true) -> nil
* attr(name, false) -> array * attr(name, false) -> nil
* *
* The first form is equivalent to #attr_reader. * The first form is equivalent to #attr_reader.
* The second form is equivalent to <code>attr_accessor(name)</code> but deprecated. * 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. * The last form is equivalent to <code>attr_reader(name)</code> but deprecated.
* Returns an array of defined methods names as symbols.
*-- *--
* \private * \private
* \todo can be static? * \todo can be static?
@ -2300,57 +2295,47 @@ VALUE
rb_mod_attr(int argc, VALUE *argv, VALUE klass) rb_mod_attr(int argc, VALUE *argv, VALUE klass)
{ {
if (argc == 2 && (argv[1] == Qtrue || argv[1] == Qfalse)) { 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_warning("optional boolean argument is obsoleted");
rb_attr(klass, id, 1, RTEST(argv[1]), TRUE); rb_attr(klass, id_for_attr(klass, argv[0]), 1, RTEST(argv[1]), TRUE);
rb_ary_push(names, ID2SYM(id)); return Qnil;
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); return rb_mod_attr_reader(argc, argv, klass);
} }
/* /*
* call-seq: * call-seq:
* attr_writer(symbol, ...) -> array * attr_writer(symbol, ...) -> nil
* attr_writer(string, ...) -> array * attr_writer(string, ...) -> nil
* *
* Creates an accessor method to allow assignment to the attribute * Creates an accessor method to allow assignment to the attribute
* <i>symbol</i><code>.id2name</code>. * <i>symbol</i><code>.id2name</code>.
* String arguments are converted to symbols. * String arguments are converted to symbols.
* Returns an array of defined methods names as symbols.
*/ */
static VALUE static VALUE
rb_mod_attr_writer(int argc, VALUE *argv, VALUE klass) rb_mod_attr_writer(int argc, VALUE *argv, VALUE klass)
{ {
int i; int i;
VALUE names = rb_ary_new2(argc);
for (i=0; i<argc; i++) { for (i=0; i<argc; i++) {
ID id = id_for_attr(klass, argv[i]); rb_attr(klass, id_for_attr(klass, argv[i]), FALSE, TRUE, TRUE);
rb_attr(klass, id, FALSE, TRUE, TRUE);
rb_ary_push(names, rb_str_intern(rb_sprintf("%"PRIsVALUE"=", ID2SYM(id))));
} }
return names; return Qnil;
} }
/* /*
* call-seq: * call-seq:
* attr_accessor(symbol, ...) -> array * attr_accessor(symbol, ...) -> nil
* attr_accessor(string, ...) -> array * attr_accessor(string, ...) -> nil
* *
* Defines a named attribute for this module, where the name is * Defines a named attribute for this module, where the name is
* <i>symbol.</i><code>id2name</code>, creating an instance variable * <i>symbol.</i><code>id2name</code>, creating an instance variable
* (<code>@name</code>) and a corresponding access method to read it. * (<code>@name</code>) and a corresponding access method to read it.
* Also creates a method called <code>name=</code> to set the attribute. * Also creates a method called <code>name=</code> to set the attribute.
* String arguments are converted to symbols. * String arguments are converted to symbols.
* Returns an array of defined methods names as symbols.
* *
* module Mod * module Mod
* attr_accessor(:one, :two) #=> [:one, :one=, :two, :two=] * attr_accessor(:one, :two)
* end * end
* Mod.instance_methods.sort #=> [:one, :one=, :two, :two=] * Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]
*/ */
@ -2359,17 +2344,11 @@ static VALUE
rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass) rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass)
{ {
int i; int i;
VALUE names = rb_ary_new2(argc * 2);
for (i=0; i<argc; i++) { for (i=0; i<argc; i++) {
ID id = id_for_attr(klass, argv[i]); rb_attr(klass, id_for_attr(klass, argv[i]), TRUE, TRUE, TRUE);
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 names; return Qnil;
} }
/* /*

View File

@ -2075,11 +2075,12 @@ check_exec_redirect1(VALUE ary, VALUE key, VALUE param)
rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param))); rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
} }
else { else {
int i; int i, n=0;
for (i = 0 ; i < RARRAY_LEN(key); i++) { for (i = 0 ; i < RARRAY_LEN(key); i++) {
VALUE v = RARRAY_AREF(key, i); VALUE v = RARRAY_AREF(key, i);
VALUE fd = check_exec_redirect_fd(v, !NIL_P(param)); VALUE fd = check_exec_redirect_fd(v, !NIL_P(param));
rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param))); rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
n++;
} }
} }
return ary; return ary;

View File

@ -13,14 +13,6 @@ def main_public_method
end end
public :main_public_method public :main_public_method
def main_public_method2
end
public :main_public_method2
def main_private_method def main_private_method
end end
private :main_private_method private :main_private_method
def main_private_method2
end
private :main_private_method2

View File

@ -4,41 +4,20 @@ require_relative 'fixtures/classes'
describe "main#private" do describe "main#private" do
after :each do after :each do
Object.send(:public, :main_public_method) Object.send(:public, :main_public_method)
Object.send(:public, :main_public_method2)
end end
context "when single argument is passed and it is not an array" do it "sets the visibility of the given method to private" do
it "sets the visibility of the given methods to private" do eval "private :main_public_method", TOPLEVEL_BINDING
eval "private :main_public_method", TOPLEVEL_BINDING Object.should have_private_method(:main_public_method)
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 end
it "returns Object" do it "returns Object" do
eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object) eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object)
end end
it "raises a NameError when at least one of given method names is undefined" do it "raises a NameError when given an undefined name" do
-> do -> do
eval "private :main_public_method, :main_undefined_method", TOPLEVEL_BINDING eval "private :main_undefined_method", TOPLEVEL_BINDING
end.should raise_error(NameError) end.should raise_error(NameError)
end end
end end

View File

@ -4,32 +4,11 @@ require_relative 'fixtures/classes'
describe "main#public" do describe "main#public" do
after :each do after :each do
Object.send(:private, :main_private_method) Object.send(:private, :main_private_method)
Object.send(:private, :main_private_method2)
end end
context "when single argument is passed and it is not an array" do it "sets the visibility of the given method to public" do
it "sets the visibility of the given methods to public" do eval "public :main_private_method", TOPLEVEL_BINDING
eval "public :main_private_method", TOPLEVEL_BINDING Object.should_not have_private_method(:main_private_method)
Object.should_not have_private_method(:main_private_method)
end
end
context "when multiple arguments are passed" do
it "sets the visibility of the given methods to public" do
eval "public :main_private_method, :main_private_method2", TOPLEVEL_BINDING
Object.should_not have_private_method(:main_private_method)
Object.should_not have_private_method(:main_private_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 public" do
eval "public [:main_private_method, :main_private_method2]", TOPLEVEL_BINDING
Object.should_not have_private_method(:main_private_method)
Object.should_not have_private_method(:main_private_method2)
end
end
end end
it "returns Object" do it "returns Object" do

View File

@ -85,19 +85,8 @@ describe "Module#alias_method" do
Module.should have_public_instance_method(:alias_method, false) Module.should have_public_instance_method(:alias_method, false)
end end
describe "returned value" do it "returns self" do
ruby_version_is ""..."3.0" do @class.send(:alias_method, :checking_return_value, :public_one).should equal(@class)
it "returns self" do
@class.send(:alias_method, :checking_return_value, :public_one).should equal(@class)
end
end
ruby_version_is "3.0" do
it "returns symbol of the defined method name" do
@class.send(:alias_method, :checking_return_value, :public_one).should equal(:checking_return_value)
@class.send(:alias_method, 'checking_return_value', :public_one).should equal(:checking_return_value)
end
end
end end
it "works in module" do it "works in module" do

View File

@ -67,22 +67,6 @@ describe "Module#attr_accessor" do
Module.should have_public_instance_method(:attr_accessor, false) Module.should have_public_instance_method(:attr_accessor, false)
end end
ruby_version_is ""..."3.0" do
it "returns nil" do
Class.new do
(attr_accessor :foo, 'bar').should == nil
end
end
end
ruby_version_is "3.0" do
it "returns an array of defined methods names as symbols" do
Class.new do
(attr_accessor :foo, 'bar').should == [:foo, :foo=, :bar, :bar=]
end
end
end
describe "on immediates" do describe "on immediates" do
before :each do before :each do
class Fixnum class Fixnum

View File

@ -61,20 +61,4 @@ describe "Module#attr_reader" do
it "is a public method" do it "is a public method" do
Module.should have_public_instance_method(:attr_reader, false) Module.should have_public_instance_method(:attr_reader, false)
end end
ruby_version_is ""..."3.0" do
it "returns nil" do
Class.new do
(attr_reader :foo, 'bar').should == nil
end
end
end
ruby_version_is "3.0" do
it "returns an array of defined methods names as symbols" do
Class.new do
(attr_reader :foo, 'bar').should == [:foo, :bar]
end
end
end
end end

View File

@ -145,24 +145,4 @@ describe "Module#attr" do
it "is a public method" do it "is a public method" do
Module.should have_public_instance_method(:attr, false) Module.should have_public_instance_method(:attr, false)
end end
ruby_version_is ""..."3.0" do
it "returns nil" do
Class.new do
(attr :foo, 'bar').should == nil
(attr :baz, false).should == nil
(attr :qux, true).should == nil
end
end
end
ruby_version_is "3.0" do
it "returns an array of defined methods names as symbols" do
Class.new do
(attr :foo, 'bar').should == [:foo, :bar]
(attr :baz, false).should == [:baz]
(attr :qux, true).should == [:qux, :qux=]
end
end
end
end end

View File

@ -61,20 +61,4 @@ describe "Module#attr_writer" do
it "is a public method" do it "is a public method" do
Module.should have_public_instance_method(:attr_writer, false) Module.should have_public_instance_method(:attr_writer, false)
end end
ruby_version_is ""..."3.0" do
it "returns nil" do
Class.new do
(attr_writer :foo, 'bar').should == nil
end
end
end
ruby_version_is "3.0" do
it "returns an array of defined methods names as symbols" do
Class.new do
(attr_writer :foo, 'bar').should == [:foo=, :bar=]
end
end
end
end end

View File

@ -6,40 +6,6 @@ describe :set_visibility, shared: true do
end end
describe "with argument" do describe "with argument" do
describe "one or more arguments" do
it "sets visibility of given method names" do
visibility = @method
old_visibility = [:protected, :private].find {|vis| vis != visibility }
mod = Module.new {
send old_visibility
def test1() end
def test2() end
send visibility, :test1, :test2
}
mod.should send(:"have_#{visibility}_instance_method", :test1, false)
mod.should send(:"have_#{visibility}_instance_method", :test2, false)
end
end
ruby_version_is "3.0" do
describe "array as a single argument" do
it "sets visibility of given method names" do
visibility = @method
old_visibility = [:protected, :private].find {|vis| vis != visibility }
mod = Module.new {
send old_visibility
def test1() end
def test2() end
send visibility, [:test1, :test2]
}
mod.should send(:"have_#{visibility}_instance_method", :test1, false)
mod.should send(:"have_#{visibility}_instance_method", :test2, false)
end
end
end
it "does not clone method from the ancestor when setting to the same visibility in a child" do it "does not clone method from the ancestor when setting to the same visibility in a child" do
visibility = @method visibility = @method
parent = Module.new { parent = Module.new {

View File

@ -1941,13 +1941,13 @@ rb_alias(VALUE klass, ID alias_name, ID original_name)
/* /*
* call-seq: * call-seq:
* alias_method(new_name, old_name) -> symbol * alias_method(new_name, old_name) -> self
* *
* Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can
* be used to retain access to methods that are overridden. * be used to retain access to methods that are overridden.
* *
* module Mod * module Mod
* alias_method :orig_exit, :exit #=> :orig_exit * alias_method :orig_exit, :exit
* def exit(code=0) * def exit(code=0)
* puts "Exiting with code #{code}" * puts "Exiting with code #{code}"
* orig_exit(code) * orig_exit(code)
@ -1968,19 +1968,8 @@ rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
if (!oldid) { if (!oldid) {
rb_print_undef_str(mod, oldname); rb_print_undef_str(mod, oldname);
} }
VALUE id = rb_to_id(newname); rb_alias(mod, rb_to_id(newname), oldid);
rb_alias(mod, id, oldid); return mod;
return ID2SYM(id);
}
static void
check_and_export_method(VALUE self, VALUE name, rb_method_visibility_t visi)
{
ID id = rb_check_id(&name);
if (!id) {
rb_print_undef_str(self, name);
}
rb_export_method(self, id, visi);
} }
static void static void
@ -1995,19 +1984,13 @@ set_method_visibility(VALUE self, int argc, const VALUE *argv, rb_method_visibil
return; return;
} }
for (i = 0; i < argc; i++) {
VALUE v; VALUE v = argv[i];
ID id = rb_check_id(&v);
if (argc == 1 && (v = rb_check_array_type(argv[0])) != Qnil) { if (!id) {
long j; rb_print_undef_str(self, v);
for (j = 0; j < RARRAY_LEN(v); j++) {
check_and_export_method(self, RARRAY_AREF(v, j), visi);
} }
} else { rb_export_method(self, id, visi);
for (i = 0; i < argc; i++) {
check_and_export_method(self, argv[i], visi);
}
} }
} }
@ -2029,7 +2012,6 @@ set_visibility(int argc, const VALUE *argv, VALUE module, rb_method_visibility_t
* public -> self * public -> self
* public(symbol, ...) -> self * public(symbol, ...) -> self
* public(string, ...) -> self * public(string, ...) -> self
* public(array) -> self
* *
* With no arguments, sets the default visibility for subsequently * With no arguments, sets the default visibility for subsequently
* defined methods to public. With arguments, sets the named methods to * defined methods to public. With arguments, sets the named methods to
@ -2048,7 +2030,6 @@ rb_mod_public(int argc, VALUE *argv, VALUE module)
* protected -> self * protected -> self
* protected(symbol, ...) -> self * protected(symbol, ...) -> self
* protected(string, ...) -> self * protected(string, ...) -> self
* protected(array) -> self
* *
* With no arguments, sets the default visibility for subsequently * With no arguments, sets the default visibility for subsequently
* defined methods to protected. With arguments, sets the named methods * defined methods to protected. With arguments, sets the named methods
@ -2076,7 +2057,6 @@ rb_mod_protected(int argc, VALUE *argv, VALUE module)
* private -> self * private -> self
* private(symbol, ...) -> self * private(symbol, ...) -> self
* private(string, ...) -> self * private(string, ...) -> self
* private(array) -> self
* *
* With no arguments, sets the default visibility for subsequently * With no arguments, sets the default visibility for subsequently
* defined methods to private. With arguments, sets the named methods * defined methods to private. With arguments, sets the named methods