aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--eval.c22
-rw-r--r--test/ruby/test_refinement.rb70
3 files changed, 95 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 2e2d2bcfca..aafe05d689 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/eval.c b/eval.c
index c1d22d66fa..9430e2bc67 100644
--- a/eval.c
+++ b/eval.c
@@ -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