1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Feature 17314: allow to pass array to public, protected and private methods

This commit is contained in:
Radosław Bułat 2020-12-18 19:17:57 +01:00 committed by Yusuke Endoh
parent 8148f88b92
commit eb8ea336d3
6 changed files with 120 additions and 14 deletions

View file

@ -249,6 +249,9 @@ 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 * Module#attr_accessor, Module#attr_reader, Module#attr_writer and Module#attr
methods now return array of defined methods names as symbols. methods now return array of defined methods names as symbols.
[[Feature #17314]] [[Feature #17314]]

View file

@ -13,6 +13,14 @@ 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,20 +4,41 @@ 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
it "sets the visibility of the given method to private" do 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 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
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 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 given an undefined name" do it "raises a NameError when at least one of given method names is undefined" do
-> 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.should raise_error(NameError)
end end
end end

View file

@ -4,12 +4,33 @@ 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
it "sets the visibility of the given method to public" do context "when single argument is passed and it is not an array" 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
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
it "returns Object" do it "returns Object" do
eval("public :main_private_method", TOPLEVEL_BINDING).should equal(Object) eval("public :main_private_method", TOPLEVEL_BINDING).should equal(Object)

View file

@ -6,6 +6,40 @@ 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

@ -1973,6 +1973,16 @@ rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
return ID2SYM(id); 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
set_method_visibility(VALUE self, int argc, const VALUE *argv, rb_method_visibility_t visi) set_method_visibility(VALUE self, int argc, const VALUE *argv, rb_method_visibility_t visi)
{ {
@ -1985,13 +1995,19 @@ set_method_visibility(VALUE self, int argc, const VALUE *argv, rb_method_visibil
return; return;
} }
for (i = 0; i < argc; i++) {
VALUE v = argv[i]; VALUE v;
ID id = rb_check_id(&v);
if (!id) { if (argc == 1 && (v = rb_check_array_type(argv[0])) != Qnil) {
rb_print_undef_str(self, v); long j;
for (j = 0; j < RARRAY_LEN(v); j++) {
check_and_export_method(self, RARRAY_AREF(v, j), visi);
}
} else {
for (i = 0; i < argc; i++) {
check_and_export_method(self, argv[i], visi);
} }
rb_export_method(self, id, visi);
} }
} }
@ -2013,6 +2029,7 @@ 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
@ -2031,6 +2048,7 @@ 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
@ -2058,6 +2076,7 @@ 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