class Mudguard::Domain::Consts

Knows all constants of the project

Constants

SEPARATOR

Public Class Methods

new(sources:) click to toggle source
# File lib/mudguard/domain/consts.rb, line 9
def initialize(sources:)
  @consts = sources.flat_map(&:find_consts).each_with_object({}, &method(:add_const))
end

Public Instance Methods

resolve(module_name, const_name) click to toggle source
# File lib/mudguard/domain/consts.rb, line 13
def resolve(module_name, const_name)
  raise Error, "const_name is undefined" if const_name.empty?

  path = split_hierarchy(module_name)
  if module_name.empty?
    # not in a module therefor const can only be defined in the root module (::)
    qualified_path(const_name)
  else
    # analyse module hierarchy to find fully qualified const name
    # resolve_in_modules(const_name, path)
    const_path = const_name.split(SEPARATOR).drop(1)
    find_const_deeper("", path, @consts, const_path) || qualified_path(const_name)
  end
end

Private Instance Methods

add_const(const, all_consts) click to toggle source
# File lib/mudguard/domain/consts.rb, line 30
def add_const(const, all_consts)
  path = split_hierarchy(const)
  const_name = path.last
  module_names = path.take(path.count - 1)
  sub_module = module_names.reduce(all_consts) { |h, m| h.key?(m) ? h[m] : h[m] = {} }
  sub_module[const_name] = {} unless sub_module.key?(const_name)
end
find_const(current_module, consts, const_path) click to toggle source
# File lib/mudguard/domain/consts.rb, line 55
def find_const(current_module, consts, const_path)
  const_name = const_path.first
  if const_path.length == 1 && consts.key?(const_name)
    # const defined in current_module
    return join_path(current_module, const_name)
  end

  # backward search (along const_path only)
  next_path = const_path.drop(1)
  found_const = find_const_deeper(const_name, next_path, consts[const_name], next_path)
  found_const ? join_path(current_module, found_const) : nil
end
find_const_deeper(current_module, remaining_modules, consts, const_path) click to toggle source
# File lib/mudguard/domain/consts.rb, line 40
def find_const_deeper(current_module, remaining_modules, consts, const_path)
  return if consts.nil?

  if remaining_modules.any?
    # Move deeper toward target module
    next_module = remaining_modules.first
    next_remaining = remaining_modules.drop(1)
    next_consts = consts[next_module]
    found_const = find_const_deeper(next_module, next_remaining, next_consts, const_path)
    return join_path(current_module, found_const) if found_const
  end

  find_const(current_module, consts, const_path)
end
join_path(module_name, const_name) click to toggle source
# File lib/mudguard/domain/consts.rb, line 68
def join_path(module_name, const_name)
  "#{module_name}#{SEPARATOR}#{const_name}"
end
qualified_path(const_name) click to toggle source
# File lib/mudguard/domain/consts.rb, line 72
def qualified_path(const_name)
  const_name =~ /^#{SEPARATOR}/ ? const_name : "#{SEPARATOR}#{const_name}"
end
split_hierarchy(module_name) click to toggle source
# File lib/mudguard/domain/consts.rb, line 76
def split_hierarchy(module_name)
  module_name.split(SEPARATOR).drop(1)
end