ruby-changes:29667
From: shugo <ko1@a...>
Date: Mon, 1 Jul 2013 12:57:27 +0900 (JST)
Subject: [ruby-changes:29667] shugo:r41719 (trunk): * eval.c (rb_using_module): activate refinements in the ancestors of
shugo 2013-07-01 12:57:16 +0900 (Mon, 01 Jul 2013) New Revision: 41719 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=41719 Log: * eval.c (rb_using_module): activate refinements in the ancestors of the argument module to support refinement inheritance by Module#include. [ruby-core:55671] [Feature #8571] * test/ruby/test_refinement.rb: related test. Modified files: trunk/ChangeLog trunk/NEWS trunk/eval.c trunk/test/ruby/test_refinement.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 41718) +++ ChangeLog (revision 41719) @@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Mon Jul 1 12:56:41 2013 Shugo Maeda <shugo@r...> + + * eval.c (rb_using_module): activate refinements in the ancestors of + the argument module to support refinement inheritance by + Module#include. [ruby-core:55671] [Feature #8571] + + * test/ruby/test_refinement.rb: related test. + Mon Jul 1 12:02:39 2013 Tanaka Akira <akr@f...> * bignum.c (rb_cstr_to_inum): Skip leading zeros. Index: eval.c =================================================================== --- eval.c (revision 41718) +++ eval.c (revision 41719) @@ -1118,19 +1118,43 @@ using_refinement(VALUE klass, VALUE modu https://github.com/ruby/ruby/blob/trunk/eval.c#L1118 return ST_CONTINUE; } -void -rb_using_module(NODE *cref, VALUE module) +static void +using_module_recursive(NODE *cref, VALUE klass) { ID id_refinements; - VALUE refinements; + VALUE super, module, refinements; - Check_Type(module, T_MODULE); + super = RCLASS_SUPER(klass); + if (super) { + using_module_recursive(cref, super); + } + switch (BUILTIN_TYPE(klass)) { + case T_MODULE: + module = klass; + break; + + case T_ICLASS: + module = RBASIC(klass)->klass; + break; + + default: + rb_raise(rb_eTypeError, "wrong argument type %s (expected Module)", + rb_obj_classname(klass)); + break; + } CONST_ID(id_refinements, "__refinements__"); refinements = rb_attr_get(module, id_refinements); if (NIL_P(refinements)) return; rb_hash_foreach(refinements, using_refinement, (VALUE) cref); } +void +rb_using_module(NODE *cref, VALUE module) +{ + Check_Type(module, T_MODULE); + using_module_recursive(cref, module); +} + VALUE rb_refinement_module_get_refined_class(VALUE module) { ID id_refined_class; Index: NEWS =================================================================== --- NEWS (revision 41718) +++ NEWS (revision 41719) @@ -46,6 +46,11 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L46 * pack/unpack (Array/String) * Q! and q! directives for long long type if platform has the type. +* toplevel + * extended methods: + * main.using activates refinements in the ancestors of the argument + module to support refinement inheritance by Module#include. + === Core classes compatibility issues (excluding feature bug fixes) * IO Index: test/ruby/test_refinement.rb =================================================================== --- test/ruby/test_refinement.rb (revision 41718) +++ test/ruby/test_refinement.rb (revision 41719) @@ -875,6 +875,60 @@ class TestRefinement < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L875 end end + class Bar + end + + module BarExt + refine Bar do + def x + return "BarExt#x" + end + end + end + + module FooBarExt + include FooExt + include BarExt + end + + module FooBarExtClient + using FooBarExt + + def self.invoke_x_on(foo) + return foo.x + end + end + + def test_module_inclusion + foo = Foo.new + assert_equal("FooExt#x", FooBarExtClient.invoke_x_on(foo)) + bar = Bar.new + assert_equal("BarExt#x", FooBarExtClient.invoke_x_on(bar)) + end + + module FooFoo2Ext + include FooExt + include FooExt2 + end + + module FooFoo2ExtClient + using FooFoo2Ext + + def self.invoke_x_on(foo) + return foo.x + end + + def self.invoke_y_on(foo) + return foo.y + end + end + + def test_module_inclusion2 + foo = Foo.new + assert_equal("FooExt2#x", FooFoo2ExtClient.invoke_x_on(foo)) + assert_equal("FooExt2#y Foo#y", FooFoo2ExtClient.invoke_y_on(foo)) + end + private def eval_using(mod, s) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/