0

All in the question, I would like to know if it's possible to do something like this in Crystal (pseudo-code) :

modules = Array(Module).new
foreach (file in specific_package) do
  if (file.is_a(crystal_module) do
    modules.push(file.module)
  end
end
Mead
  • 100
  • 10
  • Two things: 1) Crystal has no packages, the file/type relationship is a naming convention entirely. 2) You seem to be asking about a specific solution to your problem, probably one you developed in another language. It's generally better to ask about your actual problem to receive best practices in the language you're asking about. – Jonne Haß May 24 '18 at 15:59

1 Answers1

1

Crystal doesn't have packages but modules. If you want to get all modules in a file you can try this:

require "compiler/crystal/syntax"

Modules = [] of String

class ModuleVisitor < Crystal::Visitor
  def visit(node : Crystal::ModuleDef)
    Modules << node.name.names.join("::")
    true
  end

  def visit(node : Crystal::ASTNode)
    true
  end
end

Dir.glob("./*.cr").each do |file|
  visitor = ModuleVisitor.new
  parser = Crystal::Parser.new(File.read(file))
  parser.filename = file
  node = parser.parse
  node.accept(visitor)
end

puts Modules.join("\n")

Then you'd get an Array(String) with all modules names

Try it online!

If you want to get all included modules in a class try this:

class Class
  def included_modules
  {% if @type.ancestors.any? { |a| a.class.stringify.ends_with?(":Module") } %}
    {{ @type.ancestors.select { |a| a.class.stringify.ends_with?(":Module") } }}
  {% else %}
    [] of Nil
  {% end %}
  end
end

module Foo::Bar
end

class Baz
  include Foo::Bar
end

puts Baz.included_modules # => [Foo::Bar]

Try it online!

Faustino Aguilar
  • 823
  • 6
  • 15