Sha256: e4cc5edd52df8aad8bdb7940e4b70e0e1ec56d246b669af6ea98c7146642ed74

Contents?: true

Size: 1.82 KB

Versions: 2

Compression:

Stored size: 1.82 KB

Contents

require 'zeitwerk'
require 'benchmark'

class Mona::Loaders::Zeitwerk < Mona::Loaders::Base
  include Mona::Mixins

  ERROR_MESSAGE_REGEX = /expected file (?<path>[\w\/]+.rb) to define constant (?<klass>[\w:]+)/

  def initialize(...)
    @loader = Zeitwerk::Loader.new
    @loader.inflector = Class.new(Zeitwerk::Inflector).new

    super(...)
  end

  def setup
    apply_rules_for(@loader)
    @loader.setup
  end

  def eager_load
    time = Benchmark.realtime do
      @loader.eager_load
    end

    puts "eager_load dependencies in #{'%.2f' % time} seconds"
  end

  def check_classes
    check_classes_loader = @loader.dup
    check_classes_loader.on_load { |cpath, value, abspath| puts value }

    errors = []

    begin
      check_classes_loader.eager_load
    rescue Zeitwerk::NameError => e
      match = e.message.match(ERROR_MESSAGE_REGEX)

      raise e if match.nil?

      # TODO: use logger
      errors << "#{match[:path]} => #{match[:klass]}"
      check_classes_loader.ignore(match[:path])
      retry
    end

    puts errors
    raise StandardError.new("loader fails with #{errors.count} errors") if errors.any?

    nil
  end

  def apply_rules_for(entity)
    @autoload_dirs.uniq.each { entity.push_dir(_1) }
    @ignore_dirs.uniq
      .map { File.join(Mona.current_project.root_path, _1) }
      .each { entity.ignore( _1 ) }

    entity.inflector.inflect(@inflections)

    result_overwriter = ->(kname) { @overwriters.each { |o| kname = o.call(kname) }; kname }
    entity.inflector.define_singleton_method(:camelize) do |basename, abspath|
      result_overwriter.call( super(basename, abspath) )
    end
  end

  def ignore(glob)
    super(glob)

    # TODO: if loader.setup is true => push dir directly to the @loader
    @ignore_dirs
      .uniq
      .map { File.join(root_path, _1) }
      .each { @loader.ignore( _1 ) }
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
mona-0.2.3 lib/mona/loaders/zeitwerk.rb
mona-0.2.2 lib/mona/loaders/zeitwerk.rb