require "pico/context/const_resolver" module Pico class Context attr :mod, :name, :root def initialize(name, parent: nil, root:) @mod = build_mod @name = name @root = Pathname(root) if root @parent = parent end class << self def owner(const) owner, _ = Autoloader.owner_and_ascending_nibbles const owner end end def build_mod Module.new end def boot! parent.const_set name, mod end def booted? parent.const_defined? name end def eager_load! Dir[root.join('**/*.rb')].each do |rb_file| load_file rb_file end end def load_file(rb_file) mod.module_eval File.read(rb_file), rb_file.to_s end def parent return Object unless @parent Pico.contexts.fetch(@parent.to_sym).mod end def reload! shutdown! @mod = build_mod boot! end def possible_implicit_namespace?(path) root.join(path).directory? end def resolve_const(expanded_const) build_const_resolver(expanded_const).resolve end def shutdown! parent.send(:remove_const, name) end private def build_const_resolver(expanded_const) ConstResolver.new( context: self, expanded_const: String(expanded_const).dup.freeze, ) end end class AutoloadError < NameError attr :const, :rb_file def initialize(const:, rb_file:) @const = const @rb_file = rb_file end def message "Expected #{rb_file} to define #{const}" end end end