ruby-changes:70740
From: Shugo <ko1@a...>
Date: Wed, 5 Jan 2022 17:03:02 +0900 (JST)
Subject: [ruby-changes:70740] 21ee5341f8 (master): Add Module.used_refinements
https://git.ruby-lang.org/ruby.git/commit/?id=21ee5341f8 From 21ee5341f8fc4ca513295dff2148f7c203c908a7 Mon Sep 17 00:00:00 2001 From: Shugo Maeda <shugo@r...> Date: Wed, 5 Jan 2022 16:58:23 +0900 Subject: Add Module.used_refinements --- NEWS.md | 3 +++ eval.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ test/ruby/test_refinement.rb | 17 ++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/NEWS.md b/NEWS.md index 7ab42697be0..82eb55b8770 100644 --- a/NEWS.md +++ b/NEWS.md @@ -26,6 +26,9 @@ Note that each entry is kept to a minimum, see links for details. https://github.com/ruby/ruby/blob/trunk/NEWS.md#L26 Note: We're only listing outstanding class updates. +* Module + * Module.used_refinements has been added. [[Feature #14332]] + ## Stdlib updates * The following default gem are updated. diff --git a/eval.c b/eval.c index 9ba90ecdfad..8103f52fa53 100644 --- a/eval.c +++ b/eval.c @@ -1510,6 +1510,57 @@ rb_mod_s_used_modules(VALUE _) https://github.com/ruby/ruby/blob/trunk/eval.c#L1510 return rb_funcall(ary, rb_intern("uniq"), 0); } +static int +used_refinements_i(VALUE _, VALUE mod, VALUE ary) +{ + while (FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) { + rb_ary_push(ary, rb_class_of(mod)); + mod = RCLASS_SUPER(mod); + } + return ST_CONTINUE; +} + +/* + * call-seq: + * used_refinements -> array + * + * Returns an array of all modules used in the current scope. The ordering + * of modules in the resulting array is not defined. + * + * module A + * refine Object do + * end + * end + * + * module B + * refine Object do + * end + * end + * + * using A + * using B + * p Module.used_refinements + * + * <em>produces:</em> + * + * [#<refinement:Object@B>, #<refinement:Object@A>] + */ +static VALUE +rb_mod_s_used_refinements(VALUE _) +{ + const rb_cref_t *cref = rb_vm_cref(); + VALUE ary = rb_ary_new(); + + while (cref) { + if (!NIL_P(CREF_REFINEMENTS(cref))) { + rb_hash_foreach(CREF_REFINEMENTS(cref), used_refinements_i, ary); + } + cref = CREF_NEXT(cref); + } + + return ary; +} + struct refinement_import_methods_arg { rb_cref_t *cref; VALUE refinement; @@ -1944,6 +1995,8 @@ Init_eval(void) https://github.com/ruby/ruby/blob/trunk/eval.c#L1995 rb_define_private_method(rb_cModule, "using", mod_using, 1); rb_define_singleton_method(rb_cModule, "used_modules", rb_mod_s_used_modules, 0); + rb_define_singleton_method(rb_cModule, "used_refinements", + rb_mod_s_used_refinements, 0); rb_undef_method(rb_cClass, "refine"); rb_define_private_method(rb_cRefinement, "import_methods", refinement_import_methods, -1); diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index 202da136454..c6de9ed958b 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -1687,6 +1687,8 @@ class TestRefinement < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L1687 refine Object do def in_ref_a end + + RefA.const_set(:REF, self) end end @@ -1694,6 +1696,8 @@ class TestRefinement < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L1696 refine Object do def in_ref_b end + + RefB.const_set(:REF, self) end end @@ -1703,23 +1707,28 @@ class TestRefinement < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L1707 refine Object do def in_ref_c end + + RefC.const_set(:REF, self) end end module Foo using RefB USED_MODS = Module.used_modules + USED_REFS = Module.used_refinements end module Bar using RefC USED_MODS = Module.used_modules + USED_REFS = Module.used_refinements end module Combined using RefA using RefB USED_MODS = Module.used_modules + USED_REFS = Module.used_refinements end end @@ -1731,6 +1740,14 @@ class TestRefinement < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_refinement.rb#L1740 assert_equal [ref::RefB, ref::RefA], ref::Combined::USED_MODS end + def test_used_refinements + ref = VisibleRefinements + assert_equal [], Module.used_refinements + assert_equal [ref::RefB::REF], ref::Foo::USED_REFS + assert_equal [ref::RefC::REF], ref::Bar::USED_REFS + assert_equal [ref::RefB::REF, ref::RefA::REF], ref::Combined::USED_REFS + end + def test_warn_setconst_in_refinmenet bug10103 = '[ruby-core:64143] [Bug #10103]' warnings = [ -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/