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 .