How to list a class's ancestors and descendants?

How do we list a class’s ancestors and descendants in Crystal? I think the solution is related to Syntax to call ancestor's virtual method explicitly - #14 by RespiteSage ; which is actually made me thing of this question.

For example, for Ruby (see: Look up all descendants of a class in Ruby - Stack Overflow), we have:

class Parent
  def self.descendants
    ObjectSpace.each_object(Class).select { |klass| klass < self }
  end
end

class Child < Parent
end

class GrandChild < Child
end

puts Parent.descendants
puts Child.descendants

You can do this with macros: Namely by the TypeNode#ancestors, TypeNode#subclasses, and TypeNode#all_subclasses methods.

See Carcin.

EDIT: Also to be clear this happens at compile time. There isn’t a way to do this at runtime.

1 Like

Thanks @Blacksmoke16 ! This gets me really close:

class Object
  def self.ascendants
    {{@type.ancestors}}
  end
  def self.descendants
    {{@type.all_subclasses}}
  end
end
 
class Parent
end
 
class Child < Parent
end
 
class GrandChild < Child
end
 
{{puts Parent.all_subclasses}}
{{puts Child.ancestors}}
 
puts Parent.descendants
# puts Child.ascendants #=> BUG: {{ @type.name.stringify }} at /usr/lib/crystal/class.cr:149:11 should have been expanded (Exception)

… aka: Carcin

So, now I’m just waiting for a fix for {{ @type.name.stringify }} at /usr/lib/crystal/class.cr:149:11 should have been expanded · Issue #9667 · crystal-lang/crystal · GitHub .