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
|
||