Feature #7418 ยป used_refinements.patch
| eval.c | ||
|---|---|---|
| 
         return result; 
   | 
||
| 
     } 
   | 
||
| 
     static int 
   | 
||
| 
     used_refinements_i(VALUE _, VALUE mod, VALUE ary) 
   | 
||
| 
     { 
   | 
||
| 
         ID id_defined_at; 
   | 
||
| 
         CONST_ID(id_defined_at, "__defined_at__"); 
   | 
||
| 
         while(FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) { 
   | 
||
| 
     	rb_ary_push(ary, rb_attr_get(rb_class_of(mod), id_defined_at)); 
   | 
||
| 
     	mod = RCLASS_SUPER(mod); 
   | 
||
| 
         } 
   | 
||
| 
         return ST_CONTINUE; 
   | 
||
| 
     } 
   | 
||
| 
     /* 
   | 
||
| 
      *  call-seq: 
   | 
||
| 
      *     used_refinements -> array 
   | 
||
| 
      * 
   | 
||
| 
      *  Returns an array of all active refinements 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 
   | 
||
| 
      * 
   | 
||
| 
      *     module C 
   | 
||
| 
      *       using B 
   | 
||
| 
      * 
   | 
||
| 
      *       refine Object do 
   | 
||
| 
      *       end 
   | 
||
| 
      *     end 
   | 
||
| 
      * 
   | 
||
| 
      *     using A 
   | 
||
| 
      *     p used_refinements 
   | 
||
| 
      * 
   | 
||
| 
      *     C.module_eval { p used_refinements } 
   | 
||
| 
      * 
   | 
||
| 
      *  <em>produces:</em> 
   | 
||
| 
      * 
   | 
||
| 
      *     [A] 
   | 
||
| 
      *     [C, B, A] 
   | 
||
| 
      */ 
   | 
||
| 
     static VALUE 
   | 
||
| 
     rb_f_used_refinements(void) 
   | 
||
| 
     { 
   | 
||
| 
         NODE *cref = rb_vm_cref(); 
   | 
||
| 
         VALUE ary = rb_ary_new(); 
   | 
||
| 
         while(cref) { 
   | 
||
| 
     	if(!NIL_P(cref->nd_refinements)) { 
   | 
||
| 
     	    rb_hash_foreach(cref->nd_refinements, used_refinements_i, ary); 
   | 
||
| 
     	} 
   | 
||
| 
     	cref = cref->nd_next; 
   | 
||
| 
         } 
   | 
||
| 
         return rb_funcall(ary, rb_intern("uniq"), 0); 
   | 
||
| 
     } 
   | 
||
| 
     void 
   | 
||
| 
     rb_obj_call_init(VALUE obj, int argc, VALUE *argv) 
   | 
||
| 
     { 
   | 
||
| ... | ... | |
| 
         rb_define_global_function("__method__", rb_f_method_name, 0); 
   | 
||
| 
         rb_define_global_function("__callee__", rb_f_callee_name, 0); 
   | 
||
| 
         rb_define_global_function("__dir__", f_current_dirname, 0); 
   | 
||
| 
     | 
||
| 
         rb_define_global_function("used_refinements", rb_f_used_refinements, 0); 
   | 
||
| 
         rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1); 
   | 
||
| 
         rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1); 
   | 
||
| test/ruby/test_refinement.rb | ||
|---|---|---|
| 
           end 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
     | 
||
| 
       module VisibleRefinements 
   | 
||
| 
         module RefA 
   | 
||
| 
           refine Object do 
   | 
||
| 
             def in_ref_a 
   | 
||
| 
             end 
   | 
||
| 
           end 
   | 
||
| 
         end 
   | 
||
| 
         module RefB 
   | 
||
| 
           refine Object do 
   | 
||
| 
             def in_ref_b 
   | 
||
| 
             end 
   | 
||
| 
           end 
   | 
||
| 
         end 
   | 
||
| 
         module RefC 
   | 
||
| 
           using RefA 
   | 
||
| 
     | 
||
| 
           refine Object do 
   | 
||
| 
             def in_ref_c 
   | 
||
| 
             end 
   | 
||
| 
           end 
   | 
||
| 
         end 
   | 
||
| 
         module Foo 
   | 
||
| 
           using RefB 
   | 
||
| 
         end 
   | 
||
| 
         module Bar 
   | 
||
| 
           using RefC 
   | 
||
| 
         end 
   | 
||
| 
     | 
||
| 
         module Combined 
   | 
||
| 
           using Foo 
   | 
||
| 
           using Bar 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       def test_used_refinements 
   | 
||
| 
         ref = VisibleRefinements 
   | 
||
| 
         assert_equal [], used_refinements 
   | 
||
| 
         assert_equal [ref::RefB], ref::Foo.module_eval { used_refinements } 
   | 
||
| 
         assert_equal [ref::RefC, ref::RefA], ref::Bar.module_eval { used_refinements } 
   | 
||
| 
         assert_equal [ref::RefC, ref::RefA, ref::RefB], ref::Combined.module_eval { used_refinements } 
   | 
||
| 
       end 
   | 
||
| 
     end 
   | 
||