[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]