diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | eval.c | 22 | ||||
-rw-r--r-- | test/ruby/test_refinement.rb | 70 |
3 files changed, 95 insertions, 2 deletions
@@ -1,3 +1,8 @@ +Thu Nov 1 14:41:47 2012 Shugo Maeda <shugo@ruby-lang.org> + + * eval.c (rb_using_module): using should be used indirectly. + [ruby-dev:46326] [Feature #7251] + Wed Oct 31 18:17:38 2012 Narihiro Nakamura <authornari@gmail.com> * gc.c (gc_profile_record): don't define unused variables when @@ -1090,8 +1090,19 @@ rb_using_refinement(NODE *cref, VALUE klass, VALUE module) rb_clear_cache_by_class(klass); } +void rb_using_module(NODE *cref, VALUE module); + static int -using_module_i(VALUE klass, VALUE module, VALUE arg) +using_module_i(VALUE module, VALUE val, VALUE arg) +{ + NODE *cref = (NODE *) arg; + + rb_using_module(cref, module); + return ST_CONTINUE; +} + +static int +using_refinement(VALUE klass, VALUE module, VALUE arg) { NODE *cref = (NODE *) arg; @@ -1104,12 +1115,19 @@ rb_using_module(NODE *cref, VALUE module) { ID id_refinements; VALUE refinements; + ID id_using_modules; + VALUE using_modules; check_class_or_module(module); + CONST_ID(id_using_modules, "__using_modules__"); + using_modules = rb_attr_get(module, id_using_modules); + if (!NIL_P(using_modules)) { + rb_hash_foreach(using_modules, using_module_i, (VALUE) cref); + } CONST_ID(id_refinements, "__refinements__"); refinements = rb_attr_get(module, id_refinements); if (NIL_P(refinements)) return; - rb_hash_foreach(refinements, using_module_i, (VALUE) cref); + rb_hash_foreach(refinements, using_refinement, (VALUE) cref); } /* diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index fe1e23b656..cecb5a0665 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -530,4 +530,74 @@ class TestRefinement < Test::Unit::TestCase } assert_equal("no block given", e.message) end + + module IndirectUsing + class C + end + + module M1 + refine C do + def m1 + :m1 + end + end + end + + module M2 + refine C do + def m2 + :m2 + end + end + end + + module M3 + using M1 + using M2 + end + + module M + using M3 + + def self.call_m1 + C.new.m1 + end + + def self.call_m2 + C.new.m2 + end + end + end + + def test_indirect_using + assert_equal(:m1, IndirectUsing::M.call_m1) + assert_equal(:m2, IndirectUsing::M.call_m2) + end + + def test_indirect_using_module_eval + c = Class.new + m1 = Module.new { + refine c do + def m1 + :m1 + end + end + } + m2 = Module.new { + refine c do + def m2 + :m2 + end + end + } + m3 = Module.new { + using m1 + using m2 + } + m = Module.new { + using m3 + } + assert_equal(:m1, m.module_eval { c.new.m1 }) + assert_equal(:m2, m.module_eval { c.new.m2 }) + end end |