module Zeitwerk::Loader::Helpers

Constants

CNAME_VALIDATOR

— Inflection ——————————————————————————–

Private Instance Methods

cname_for(basename, abspath) click to toggle source

@raise [Zeitwerk::NameError] @sig (String, String) -> Symbol

# File lib/zeitwerk/loader/helpers.rb, line 110
          def cname_for(basename, abspath)
    cname = inflector.camelize(basename, abspath)

    unless cname.is_a?(String)
      raise TypeError, "#{inflector.class}#camelize must return a String, received #{cname.inspect}"
    end

    if cname.include?("::")
      raise Zeitwerk::NameError.new(<<~MESSAGE, cname)
        wrong constant name #{cname} inferred by #{inflector.class} from

          #{abspath}

        #{inflector.class}#camelize should return a simple constant name without "::"
      MESSAGE
    end

    begin
      CNAME_VALIDATOR.const_defined?(cname, false)
    rescue ::NameError => error
      path_type = ruby?(abspath) ? "file" : "directory"

      raise Zeitwerk::NameError.new(<<~MESSAGE, error.name)
        #{error.message} inferred by #{inflector.class} from #{path_type}

          #{abspath}

        Possible ways to address this:

          * Tell Zeitwerk to ignore this particular #{path_type}.
          * Tell Zeitwerk to ignore one of its parent directories.
          * Rename the #{path_type} to comply with the naming conventions.
          * Modify the inflector to handle this case.
      MESSAGE
    end

    cname.to_sym
  end
dir?(path) click to toggle source

@sig (String) -> bool

# File lib/zeitwerk/loader/helpers.rb, line 85
        def dir?(path)
  File.directory?(path)
end
has_at_least_one_ruby_file?(dir) click to toggle source

Looks for a Ruby file using breadth-first search. This type of search is important to list as less directories as possible and return fast in the common case in which there are Ruby files.

@sig (String) -> bool

# File lib/zeitwerk/loader/helpers.rb, line 56
        def has_at_least_one_ruby_file?(dir)
  to_visit = [dir]

  while (dir = to_visit.shift)
    children = Dir.children(dir)

    children.each do |basename|
      next if hidden?(basename)

      abspath = File.join(dir, basename)
      next if ignored_path?(abspath)

      if dir?(abspath)
        to_visit << abspath unless roots.key?(abspath)
      else
        return true if ruby?(abspath)
      end
    end
  end

  false
end
hidden?(basename) click to toggle source

@sig (String) -> bool

# File lib/zeitwerk/loader/helpers.rb, line 90
        def hidden?(basename)
  basename.start_with?(".")
end
log(message) click to toggle source

@sig (String) -> void

# File lib/zeitwerk/loader/helpers.rb, line 7
        def log(message)
  method_name = logger.respond_to?(:debug) ? :debug : :call
  logger.send(method_name, "Zeitwerk@#{tag}: #{message}")
end
ls(dir) { |basename, freeze, ftype| ... } click to toggle source

@sig (String) { (String, String) -> void } -> void

# File lib/zeitwerk/loader/helpers.rb, line 15
        def ls(dir)
  children = Dir.children(dir)

  # The order in which a directory is listed depends on the file system.
  #
  # Since client code may run in different platforms, it seems convenient to
  # order directory entries. This provides consistent eager loading across
  # platforms, for example.
  children.sort!

  children.each do |basename|
    next if hidden?(basename)

    abspath = File.join(dir, basename)
    next if ignored_path?(abspath)

    if dir?(abspath)
      next if roots.key?(abspath)

      if !has_at_least_one_ruby_file?(abspath)
        log("directory #{abspath} is ignored because it has no Ruby files") if logger
        next
      end

      ftype = :directory
    else
      next unless ruby?(abspath)
      ftype = :file
    end

    # We freeze abspath because that saves allocations when passed later to
    # File methods. See #125.
    yield basename, abspath.freeze, ftype
  end
end
ruby?(path) click to toggle source

@sig (String) -> bool

# File lib/zeitwerk/loader/helpers.rb, line 80
        def ruby?(path)
  path.end_with?(".rb")
end
walk_up(abspath) { |abspath| ... } click to toggle source

@sig (String) { (String) -> void } -> void

# File lib/zeitwerk/loader/helpers.rb, line 95
        def walk_up(abspath)
  loop do
    yield abspath
    abspath, basename = File.split(abspath)
    break if basename == "/"
  end
end