mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* class.c (rb_prepend_module): move refined methods from the origin
of a class to the class, because refinements should have priority over prepended modules. * test/ruby/test_refinement.rb: related test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38344 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a773539d3a
commit
75bed271f0
3 changed files with 82 additions and 0 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
Wed Dec 12 18:30:29 2012 Shugo Maeda <shugo@ruby-lang.org>
|
||||||
|
|
||||||
|
* class.c (rb_prepend_module): move refined methods from the origin
|
||||||
|
of a class to the class, because refinements should have priority
|
||||||
|
over prepended modules.
|
||||||
|
|
||||||
|
* test/ruby/test_refinement.rb: related test.
|
||||||
|
|
||||||
Wed Dec 12 18:27:09 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Wed Dec 12 18:27:09 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* time.c (zone_str): lookup or insert by using st_update() at once.
|
* time.c (zone_str): lookup or insert by using st_update() at once.
|
||||||
|
|
29
class.c
29
class.c
|
@ -731,6 +731,33 @@ include_modules_at(VALUE klass, VALUE c, VALUE module)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
move_refined_method(st_data_t key, st_data_t value, st_data_t data)
|
||||||
|
{
|
||||||
|
rb_method_entry_t *me = (rb_method_entry_t *) value;
|
||||||
|
st_table *tbl = (st_table *) data;
|
||||||
|
|
||||||
|
if (me->def->type == VM_METHOD_TYPE_REFINED) {
|
||||||
|
if (me->def->body.orig_me) {
|
||||||
|
rb_method_entry_t *orig_me = me->def->body.orig_me, *new_me;
|
||||||
|
me->def->body.orig_me = NULL;
|
||||||
|
new_me = ALLOC(rb_method_entry_t);
|
||||||
|
*new_me = *me;
|
||||||
|
st_add_direct(tbl, key, (st_data_t) new_me);
|
||||||
|
*me = *orig_me;
|
||||||
|
xfree(orig_me);
|
||||||
|
return ST_CONTINUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
st_add_direct(tbl, key, (st_data_t) me);
|
||||||
|
return ST_DELETE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ST_CONTINUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_prepend_module(VALUE klass, VALUE module)
|
rb_prepend_module(VALUE klass, VALUE module)
|
||||||
{
|
{
|
||||||
|
@ -754,6 +781,8 @@ rb_prepend_module(VALUE klass, VALUE module)
|
||||||
RCLASS_ORIGIN(klass) = origin;
|
RCLASS_ORIGIN(klass) = origin;
|
||||||
RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass);
|
RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass);
|
||||||
RCLASS_M_TBL(klass) = st_init_numtable();
|
RCLASS_M_TBL(klass) = st_init_numtable();
|
||||||
|
st_foreach(RCLASS_M_TBL(origin), move_refined_method,
|
||||||
|
(st_data_t) RCLASS_M_TBL(klass));
|
||||||
}
|
}
|
||||||
changed = include_modules_at(klass, klass, module);
|
changed = include_modules_at(klass, klass, module);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
|
|
|
@ -755,6 +755,51 @@ class TestRefinement < Test::Unit::TestCase
|
||||||
PrependIntoRefinement::User.invoke_baz_on(x))
|
PrependIntoRefinement::User.invoke_baz_on(x))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module PrependAfterRefine
|
||||||
|
class C
|
||||||
|
def foo
|
||||||
|
"original"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module M
|
||||||
|
refine C do
|
||||||
|
def foo
|
||||||
|
"refined"
|
||||||
|
end
|
||||||
|
|
||||||
|
def bar
|
||||||
|
"refined"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module Mixin
|
||||||
|
def foo
|
||||||
|
"mixin"
|
||||||
|
end
|
||||||
|
|
||||||
|
def bar
|
||||||
|
"mixin"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class C
|
||||||
|
prepend Mixin
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_prepend_after_refine
|
||||||
|
x = eval_using(PrependAfterRefine::M,
|
||||||
|
"TestRefinement::PrependAfterRefine::C.new.foo")
|
||||||
|
assert_equal("refined", x)
|
||||||
|
assert_equal("mixin", TestRefinement::PrependAfterRefine::C.new.foo)
|
||||||
|
y = eval_using(PrependAfterRefine::M,
|
||||||
|
"TestRefinement::PrependAfterRefine::C.new.bar")
|
||||||
|
assert_equal("refined", y)
|
||||||
|
assert_equal("mixin", TestRefinement::PrependAfterRefine::C.new.bar)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def eval_using(mod, s)
|
def eval_using(mod, s)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue