mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* eval.c (mod_using): new method Module#using, which activates
refinements of the specified module only in the current class or module definition. [ruby-core:55273] [Feature #8481] * test/ruby/test_refinement.rb: related test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1f828497d1
commit
17f1cdaa00
3 changed files with 96 additions and 9 deletions
|
@ -1,3 +1,11 @@
|
|||
Wed Jun 12 23:27:03 2013 Shugo Maeda <shugo@ruby-lang.org>
|
||||
|
||||
* eval.c (mod_using): new method Module#using, which activates
|
||||
refinements of the specified module only in the current class or
|
||||
module definition. [ruby-core:55273] [Feature #8481]
|
||||
|
||||
* test/ruby/test_refinement.rb: related test.
|
||||
|
||||
Wed Jun 12 22:58:48 2013 Shugo Maeda <shugo@ruby-lang.org>
|
||||
|
||||
* safe.c (rb_set_safe_level, safe_setter): raise an ArgumentError
|
||||
|
|
32
eval.c
32
eval.c
|
@ -1226,6 +1226,34 @@ rb_mod_refine(VALUE module, VALUE klass)
|
|||
return refinement;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* using(module) -> self
|
||||
*
|
||||
* Import class refinements from <i>module</i> into the current class or
|
||||
* module definition.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
mod_using(VALUE self, VALUE module)
|
||||
{
|
||||
NODE *cref = rb_vm_cref();
|
||||
rb_control_frame_t *prev_cfp = previous_frame(GET_THREAD());
|
||||
|
||||
warn_refinements_once();
|
||||
if (prev_frame_func()) {
|
||||
rb_raise(rb_eRuntimeError,
|
||||
"Module#using is not permitted in methods");
|
||||
}
|
||||
if (prev_cfp && prev_cfp->self != self) {
|
||||
rb_raise(rb_eRuntimeError, "Module#using is not called on self");
|
||||
}
|
||||
Check_Type(module, T_MODULE);
|
||||
rb_using_module(cref, module);
|
||||
rb_clear_cache();
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
|
||||
{
|
||||
|
@ -1354,7 +1382,8 @@ top_using(VALUE self, VALUE module)
|
|||
|
||||
warn_refinements_once();
|
||||
if (cref->nd_next || (prev_cfp && prev_cfp->me)) {
|
||||
rb_raise(rb_eRuntimeError, "using is permitted only at toplevel");
|
||||
rb_raise(rb_eRuntimeError,
|
||||
"main.using is permitted only at toplevel");
|
||||
}
|
||||
Check_Type(module, T_MODULE);
|
||||
rb_using_module(cref, module);
|
||||
|
@ -1558,6 +1587,7 @@ Init_eval(void)
|
|||
rb_define_private_method(rb_cModule, "prepend_features", rb_mod_prepend_features, 1);
|
||||
rb_define_private_method(rb_cModule, "prepend", rb_mod_prepend, -1);
|
||||
rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1);
|
||||
rb_define_private_method(rb_cModule, "using", mod_using, 1);
|
||||
rb_undef_method(rb_cClass, "refine");
|
||||
|
||||
rb_undef_method(rb_cClass, "module_function");
|
||||
|
|
|
@ -429,14 +429,6 @@ class TestRefinement < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_no_module_using
|
||||
assert_raise(NoMethodError) do
|
||||
Module.new {
|
||||
using Module.new
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
class UsingClass
|
||||
end
|
||||
|
||||
|
@ -826,6 +818,63 @@ class TestRefinement < Test::Unit::TestCase
|
|||
assert_equal([:foo, :ref, bug7925], x, bug7925)
|
||||
end
|
||||
|
||||
module ModuleUsing
|
||||
using FooExt
|
||||
|
||||
def self.invoke_x_on(foo)
|
||||
return foo.x
|
||||
end
|
||||
|
||||
def self.invoke_y_on(foo)
|
||||
return foo.y
|
||||
end
|
||||
|
||||
def self.invoke_z_on(foo)
|
||||
return foo.z
|
||||
end
|
||||
|
||||
def self.send_z_on(foo)
|
||||
return foo.send(:z)
|
||||
end
|
||||
|
||||
def self.method_z(foo)
|
||||
return foo.method(:z)
|
||||
end
|
||||
|
||||
def self.invoke_call_x_on(foo)
|
||||
return foo.call_x
|
||||
end
|
||||
end
|
||||
|
||||
def test_module_using
|
||||
foo = Foo.new
|
||||
assert_equal("Foo#x", foo.x)
|
||||
assert_equal("Foo#y", foo.y)
|
||||
assert_raise(NoMethodError) { foo.z }
|
||||
assert_equal("FooExt#x", ModuleUsing.invoke_x_on(foo))
|
||||
assert_equal("FooExt#y Foo#y", ModuleUsing.invoke_y_on(foo))
|
||||
assert_equal("FooExt#z", ModuleUsing.invoke_z_on(foo))
|
||||
assert_equal("Foo#x", foo.x)
|
||||
assert_equal("Foo#y", foo.y)
|
||||
assert_raise(NoMethodError) { foo.z }
|
||||
end
|
||||
|
||||
def test_module_using_in_method
|
||||
assert_raise(RuntimeError) do
|
||||
Module.new.send(:using, FooExt)
|
||||
end
|
||||
end
|
||||
|
||||
def test_module_using_invalid_self
|
||||
assert_raise(RuntimeError) do
|
||||
eval <<-EOF, TOPLEVEL_BINDING
|
||||
module TestRefinement::TestModuleUsingInvalidSelf
|
||||
Module.new.send(:using, TestRefinement::FooExt)
|
||||
end
|
||||
EOF
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def eval_using(mod, s)
|
||||
|
|
Loading…
Add table
Reference in a new issue