* eval.c (rb_mod_refine): refine modules as well.
[ruby-core:76199] [Feature #12534] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56213 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
0b5a4e68c3
commit
a463ab1f05
@ -1,3 +1,8 @@
|
|||||||
|
Fri Sep 23 20:36:05 2016 Shugo Maeda <shugo@ruby-lang.org>
|
||||||
|
|
||||||
|
* eval.c (rb_mod_refine): refine modules as well.
|
||||||
|
[ruby-core:76199] [Feature #12534]
|
||||||
|
|
||||||
Fri Sep 23 20:19:09 2016 Akinori MUSHA <knu@iDaemons.org>
|
Fri Sep 23 20:19:09 2016 Akinori MUSHA <knu@iDaemons.org>
|
||||||
|
|
||||||
* man/ruby.1: Update the paragraphs in "Rich Libraries" which
|
* man/ruby.1: Update the paragraphs in "Rich Libraries" which
|
||||||
|
13
diff
Normal file
13
diff
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
diff --git a/tool/mkconfig.rb b/tool/mkconfig.rb
|
||||||
|
index 6b6f14c..ee0642c 100755
|
||||||
|
--- a/tool/mkconfig.rb
|
||||||
|
+++ b/tool/mkconfig.rb
|
||||||
|
@@ -20,7 +20,7 @@
|
||||||
|
require "fileutils"
|
||||||
|
mkconfig = File.basename($0)
|
||||||
|
|
||||||
|
-fast = {'prefix'=>TRUE, 'ruby_install_name'=>TRUE, 'INSTALL'=>TRUE, 'EXEEXT'=>TRUE}
|
||||||
|
+fast = {'prefix'=>true, 'ruby_install_name'=>true, 'INSTALL'=>true, 'EXEEXT'=>true}
|
||||||
|
|
||||||
|
win32 = /mswin/ =~ arch
|
||||||
|
universal = /universal.*darwin/ =~ arch
|
20
eval.c
20
eval.c
@ -1092,6 +1092,16 @@ rb_mod_prepend(int argc, VALUE *argv, VALUE module)
|
|||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_class_or_module(VALUE obj)
|
||||||
|
{
|
||||||
|
if (!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE)) {
|
||||||
|
rb_raise(rb_eTypeError,
|
||||||
|
"wrong argument type %"PRIsVALUE" (expected Class or Module)",
|
||||||
|
rb_obj_class(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
hidden_identity_hash_new(void)
|
hidden_identity_hash_new(void)
|
||||||
{
|
{
|
||||||
@ -1106,7 +1116,7 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
|
|||||||
{
|
{
|
||||||
VALUE iclass, c, superclass = klass;
|
VALUE iclass, c, superclass = klass;
|
||||||
|
|
||||||
Check_Type(klass, T_CLASS);
|
ensure_class_or_module(klass);
|
||||||
Check_Type(module, T_MODULE);
|
Check_Type(module, T_MODULE);
|
||||||
if (NIL_P(CREF_REFINEMENTS(cref))) {
|
if (NIL_P(CREF_REFINEMENTS(cref))) {
|
||||||
CREF_REFINEMENTS_SET(cref, hidden_identity_hash_new());
|
CREF_REFINEMENTS_SET(cref, hidden_identity_hash_new());
|
||||||
@ -1231,11 +1241,11 @@ add_activated_refinement(VALUE activated_refinements,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* refine(klass) { block } -> module
|
* refine(mod) { block } -> module
|
||||||
*
|
*
|
||||||
* Refine <i>klass</i> in the receiver.
|
* Refine <i>mod</i> in the receiver.
|
||||||
*
|
*
|
||||||
* Returns an overlaid module.
|
* Returns a module, where refined methods are defined.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
@ -1255,7 +1265,7 @@ rb_mod_refine(VALUE module, VALUE klass)
|
|||||||
rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
|
rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
|
||||||
}
|
}
|
||||||
|
|
||||||
Check_Type(klass, T_CLASS);
|
ensure_class_or_module(klass);
|
||||||
CONST_ID(id_refinements, "__refinements__");
|
CONST_ID(id_refinements, "__refinements__");
|
||||||
refinements = rb_attr_get(module, id_refinements);
|
refinements = rb_attr_get(module, id_refinements);
|
||||||
if (NIL_P(refinements)) {
|
if (NIL_P(refinements)) {
|
||||||
|
@ -345,19 +345,66 @@ class TestRefinement < Test::Unit::TestCase
|
|||||||
assert_equal([:c, :m1, :m2], x)
|
assert_equal([:c, :m1, :m2], x)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_refine_module
|
module RefineModule
|
||||||
m1 = Module.new
|
module M
|
||||||
assert_raise(TypeError) do
|
|
||||||
Module.new {
|
|
||||||
refine m1 do
|
|
||||||
def foo
|
def foo
|
||||||
:m2
|
"M#foo"
|
||||||
|
end
|
||||||
|
|
||||||
|
def bar
|
||||||
|
"M#bar"
|
||||||
|
end
|
||||||
|
|
||||||
|
def baz
|
||||||
|
"M#baz"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
|
||||||
|
class C
|
||||||
|
include M
|
||||||
|
|
||||||
|
def baz
|
||||||
|
"#{super} C#baz"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module M2
|
||||||
|
refine M do
|
||||||
|
def foo
|
||||||
|
"M@M2#foo"
|
||||||
|
end
|
||||||
|
|
||||||
|
def bar
|
||||||
|
"#{super} M@M2#bar"
|
||||||
|
end
|
||||||
|
|
||||||
|
def baz
|
||||||
|
"#{super} M@M2#baz"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
using M2
|
||||||
|
|
||||||
|
def self.call_foo
|
||||||
|
C.new.foo
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.call_bar
|
||||||
|
C.new.bar
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.call_baz
|
||||||
|
C.new.baz
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_refine_module
|
||||||
|
assert_equal("M@M2#foo", RefineModule.call_foo)
|
||||||
|
assert_equal("M#bar M@M2#bar", RefineModule.call_bar)
|
||||||
|
assert_equal("M#baz C#baz", RefineModule.call_baz)
|
||||||
|
end
|
||||||
|
|
||||||
def test_refine_neither_class_nor_module
|
def test_refine_neither_class_nor_module
|
||||||
assert_raise(TypeError) do
|
assert_raise(TypeError) do
|
||||||
Module.new {
|
Module.new {
|
||||||
|
@ -439,13 +439,17 @@ make_method_entry_refined(VALUE owner, rb_method_entry_t *me)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct {
|
struct {
|
||||||
const struct rb_method_entry_struct *orig_me;
|
struct rb_method_entry_struct *orig_me;
|
||||||
VALUE owner;
|
VALUE owner;
|
||||||
} refined;
|
} refined;
|
||||||
|
|
||||||
rb_vm_check_redefinition_opt_method(me, me->owner);
|
rb_vm_check_redefinition_opt_method(me, me->owner);
|
||||||
|
|
||||||
refined.orig_me = rb_method_entry_clone(me);
|
refined.orig_me =
|
||||||
|
rb_method_entry_alloc(me->called_id, me->owner,
|
||||||
|
me->defined_class || owner,
|
||||||
|
method_definition_addref(me->def));
|
||||||
|
METHOD_ENTRY_FLAGS_COPY(refined.orig_me, me);
|
||||||
refined.owner = owner;
|
refined.owner = owner;
|
||||||
|
|
||||||
method_definition_set(me, method_definition_create(VM_METHOD_TYPE_REFINED, me->called_id), (void *)&refined);
|
method_definition_set(me, method_definition_create(VM_METHOD_TYPE_REFINED, me->called_id), (void *)&refined);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user