Module: Im::Registry

Defined in:
lib/im/registry.rb

Overview

:nodoc: all

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.autoloaded_modulesObject (readonly)



73
74
75
# File 'lib/im/registry.rb', line 73

def autoloaded_modules
  @autoloaded_modules
end

.autoloadsObject (readonly)

Maps absolute paths to the loaders responsible for them.

This information is used by our decorated ‘Kernel#require` to be able to invoke callbacks and autovivify modules.



26
27
28
# File 'lib/im/registry.rb', line 26

def autoloads
  @autoloads
end

.gem_loaders_by_root_fileObject (readonly)

Registers gem loaders to let ‘for_gem` be idempotent in case of reload.



17
18
19
# File 'lib/im/registry.rb', line 17

def gem_loaders_by_root_file
  @gem_loaders_by_root_file
end

.inceptionsObject (readonly)

This hash table addresses an edge case in which an autoload is ignored.

For example, let’s suppose we want to autoload in a gem like this:

# lib/my_gem.rb
loader = Im::Loader.new
loader.push_dir(__dir__)
loader.setup

module loader::MyGem
end

if you require “my_gem”, as Bundler would do, this happens while setting up autoloads:

1. Object.autoload?(:MyGem) returns `nil` because the autoload for
   the constant is issued by Im while the same file is being
   required.
2. The constant `MyGem` is undefined while setup runs.

Therefore, a directory ‘lib/my_gem` would autovivify a module according to the existing information. But that would be wrong.

To overcome this fundamental limitation, we keep track of the constant paths that are in this situation —in the example above, “MyGem”— and take this collection into account for the autovivification logic.

Note that you cannot generally address this by moving the setup code below the constant definition, because we want libraries to be able to use managed constants in the module body:

module loader::MyGem
  include MyConcern
end


69
70
71
# File 'lib/im/registry.rb', line 69

def inceptions
  @inceptions
end

.loadersObject (readonly)

Keeps track of all loaders. Useful to broadcast messages and to prevent them from being garbage collected.



11
12
13
# File 'lib/im/registry.rb', line 11

def loaders
  @loaders
end

.pathsObject (readonly)



30
31
32
# File 'lib/im/registry.rb', line 30

def paths
  @paths
end

Class Method Details

.inception?(cpath) ⇒ Boolean

Returns:

  • (Boolean)


135
136
137
138
139
# File 'lib/im/registry.rb', line 135

def inception?(cpath)
  if pair = inceptions[cpath]
    pair.first
  end
end

.loader_for(path) ⇒ Object



147
148
149
# File 'lib/im/registry.rb', line 147

def loader_for(path)
  paths[path]
end

.loader_for_gem(root_file, warn_on_extra_files:) ⇒ Object

This method returns always a loader, the same instance for the same root file. That is how Im::Loader.for_gem is idempotent.



99
100
101
# File 'lib/im/registry.rb', line 99

def loader_for_gem(root_file, warn_on_extra_files:)
  gem_loaders_by_root_file[root_file] ||= GemLoader._new(root_file, warn_on_extra_files: warn_on_extra_files)
end

.on_unload(loader) ⇒ Object



153
154
155
156
# File 'lib/im/registry.rb', line 153

def on_unload(loader)
  autoloads.delete_if { |_path, object| object == loader }
  inceptions.delete_if { |_cpath, (_path, object)| object == loader }
end

.register_autoload(loader, abspath) ⇒ Object



105
106
107
# File 'lib/im/registry.rb', line 105

def register_autoload(loader, abspath)
  paths[abspath] = autoloads[abspath] = loader
end

.register_autoloaded_module(mod, module_name, loader) ⇒ Object



141
142
143
# File 'lib/im/registry.rb', line 141

def register_autoloaded_module(mod, module_name, loader)
  autoloaded_modules[mod.object_id] = [module_name, loader, []]
end

.register_inception(cpath, abspath, loader) ⇒ Object



129
130
131
# File 'lib/im/registry.rb', line 129

def register_inception(cpath, abspath, loader)
  inceptions[cpath] = [abspath, loader]
end

.register_loader(loader) ⇒ Object

Registers a loader.



79
80
81
# File 'lib/im/registry.rb', line 79

def register_loader(loader)
  loaders << loader
end

.register_path(loader, abspath) ⇒ Object



117
118
119
# File 'lib/im/registry.rb', line 117

def register_path(loader, abspath)
  paths[abspath] = loader
end

.unregister_autoload(abspath) ⇒ Object



111
112
113
# File 'lib/im/registry.rb', line 111

def unregister_autoload(abspath)
  autoloads.delete(abspath)
end

.unregister_loader(loader) ⇒ Object



85
86
87
88
89
90
91
92
# File 'lib/im/registry.rb', line 85

def unregister_loader(loader)
  loaders.delete(loader)
  gem_loaders_by_root_file.delete_if { |_, l| l == loader }
  autoloads.delete_if { |_, l| l == loader }
  paths.delete_if { |_, l| l == loader }
  inceptions.delete_if { |_, (_, l)| l == loader }
  autoloaded_modules.delete_if { |_, (_, l, _)| l == loader }
end

.unregister_path(abspath) ⇒ Object



123
124
125
# File 'lib/im/registry.rb', line 123

def unregister_path(abspath)
  paths.delete(abspath)
end