summaryrefslogtreecommitdiff
path: root/class.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-10-26 10:35:21 -0900
committerGitHub <noreply@github.com>2021-10-26 12:35:21 -0700
commit717ab0bb2ee63dfe76076e0c9f91fbac3a0de4fd (patch)
treed2b531647657dd58e6ce6e64e3f6fa0adaa75f40 /class.c
parenta4d5ee4f31bf3ff36c1a8c8fe3cda16aa1016b12 (diff)
Add Class#descendants
Doesn't include receiver or singleton classes. Implements [Feature #14394] Co-authored-by: fatkodima <fatkodima123@gmail.com> Co-authored-by: Benoit Daloze <eregontp@gmail.com>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4974 Merged-By: jeremyevans <code@jeremyevans.net>
Diffstat (limited to 'class.c')
-rw-r--r--class.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/class.c b/class.c
index 8b0bfb8387..6bf17aaa47 100644
--- a/class.c
+++ b/class.c
@@ -1335,6 +1335,41 @@ rb_mod_ancestors(VALUE mod)
}
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)
{
rb_ary_push((VALUE)ary, ID2SYM((ID)name));