From 717ab0bb2ee63dfe76076e0c9f91fbac3a0de4fd Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Tue, 26 Oct 2021 10:35:21 -0900 Subject: Add Class#descendants Doesn't include receiver or singleton classes. Implements [Feature #14394] Co-authored-by: fatkodima Co-authored-by: Benoit Daloze --- class.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'class.c') diff --git a/class.c b/class.c index 8b0bfb8387..6bf17aaa47 100644 --- a/class.c +++ b/class.c @@ -1334,6 +1334,41 @@ rb_mod_ancestors(VALUE mod) return ary; } +static void +class_descendants_recursive(VALUE klass, VALUE ary) +{ + if (BUILTIN_TYPE(klass) == T_CLASS && !FL_TEST(klass, FL_SINGLETON)) { + rb_ary_push(ary, klass); + } + rb_class_foreach_subclass(klass, class_descendants_recursive, ary); +} + +/* + * call-seq: + * descendants -> array + * + * Returns an array of classes where the receiver is one of + * the ancestors of the class, excluding the receiver and + * singleton classes. The order of the returned array is not + * defined. + * + * class A; end + * class B < A; end + * class C < B; end + * + * A.descendants #=> [B, C] + * B.descendants #=> [C] + * C.descendants #=> [] + */ + +VALUE +rb_class_descendants(VALUE klass) +{ + VALUE ary = rb_ary_new(); + rb_class_foreach_subclass(klass, class_descendants_recursive, ary); + return ary; +} + static void ins_methods_push(st_data_t name, st_data_t ary) { -- cgit v1.2.3