Class: DeepCover::AutoloadTracker
- Inherits:
-
Object
- Object
- DeepCover::AutoloadTracker
- Defined in:
- lib/deep_cover/autoload_tracker.rb
Defined Under Namespace
Classes: AutoloadEntry
Class Attribute Summary collapse
-
.warned_for_frozen_module ⇒ Object
Returns the value of attribute warned_for_frozen_module.
Instance Attribute Summary collapse
-
#autoloads_by_basename ⇒ Object
readonly
Returns the value of attribute autoloads_by_basename.
-
#interceptor_files_by_path ⇒ Object
readonly
Returns the value of attribute interceptor_files_by_path.
Class Method Summary collapse
-
.warn_frozen_module(mod) ⇒ Object
Using frozen modules/classes is almost unheard of, but a warning makes things easier if someone does it.
Instance Method Summary collapse
- #autoload_path_for(mod, name, path) ⇒ Object
-
#initialize ⇒ AutoloadTracker
constructor
A new instance of AutoloadTracker.
-
#initialize_autoloaded_paths(mods = ObjectSpace.each_object(Module)) ⇒ Object
This is only used on MRI, so ObjectSpace is alright.
- #possible_autoload_target?(requested_path) ⇒ Boolean
-
#remove_interceptors ⇒ Object
We need to remove the interceptor hooks, otherwise, the problem if manually requiring something that is autoloaded will cause issues.
-
#wrap_require(requested_path, absolute_path_found) ⇒ Object
&block.
Constructor Details
#initialize ⇒ AutoloadTracker
Returns a new instance of AutoloadTracker.
27 28 29 30 |
# File 'lib/deep_cover/autoload_tracker.rb', line 27 def initialize @autoloads_by_basename = {} @interceptor_files_by_path = {} end |
Class Attribute Details
.warned_for_frozen_module ⇒ Object
Returns the value of attribute warned_for_frozen_module.
112 113 114 |
# File 'lib/deep_cover/autoload_tracker.rb', line 112 def warned_for_frozen_module @warned_for_frozen_module end |
Instance Attribute Details
#autoloads_by_basename ⇒ Object (readonly)
Returns the value of attribute autoloads_by_basename.
26 27 28 |
# File 'lib/deep_cover/autoload_tracker.rb', line 26 def autoloads_by_basename @autoloads_by_basename end |
#interceptor_files_by_path ⇒ Object (readonly)
Returns the value of attribute interceptor_files_by_path.
26 27 28 |
# File 'lib/deep_cover/autoload_tracker.rb', line 26 def interceptor_files_by_path @interceptor_files_by_path end |
Class Method Details
.warn_frozen_module(mod) ⇒ Object
Using frozen modules/classes is almost unheard of, but a warning makes things easier if someone does it
117 118 119 120 121 122 |
# File 'lib/deep_cover/autoload_tracker.rb', line 117 def self.warn_frozen_module(mod) return if warned_for_frozen_module self.warned_for_frozen_module ||= true warn "There is an autoload on a frozen module/class: #{mod}, DeepCover cannot handle those, failure is probable. " \ "This warning won't be displayed again (even for different module/class)" end |
Instance Method Details
#autoload_path_for(mod, name, path) ⇒ Object
32 33 34 35 36 37 38 39 40 |
# File 'lib/deep_cover/autoload_tracker.rb', line 32 def autoload_path_for(mod, name, path) interceptor_path = setup_interceptor_for(mod, name, path) if DeepCover.custom_requirer.is_being_required?(path) already_loaded_feature else interceptor_path end end |
#initialize_autoloaded_paths(mods = ObjectSpace.each_object(Module)) ⇒ Object
This is only used on MRI, so ObjectSpace is alright.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/deep_cover/autoload_tracker.rb', line 71 def initialize_autoloaded_paths(mods = ObjectSpace.each_object(Module)) # &do_autoload_block mods.each do |mod| # Module's constants are shared with Object. But if you set autoloads directly on Module, they # appear on multiple classes. So just skip, Object will take care of those. next if mod == Module if mod.frozen? if mod.constants.any? { |name| mod.autoload?(name) } self.class.warn_frozen_module(mod) end next end mod.constants.each do |name| path = mod.autoload?(name) next unless path interceptor_path = setup_interceptor_for(mod, name, path) yield mod, name, interceptor_path end end end |
#possible_autoload_target?(requested_path) ⇒ Boolean
42 43 44 45 46 |
# File 'lib/deep_cover/autoload_tracker.rb', line 42 def possible_autoload_target?(requested_path) basename = basename_without_extension(requested_path) autoloads = @autoloads_by_basename[basename] autoloads && !autoloads.empty? end |
#remove_interceptors ⇒ Object
We need to remove the interceptor hooks, otherwise, the problem if manually requiring something that is autoloaded will cause issues.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/deep_cover/autoload_tracker.rb', line 95 def remove_interceptors # &do_autoload_block @autoloads_by_basename.each do |basename, entries| entries.each do |entry| mod = entry.mod_if_available next unless mod # Module's constants are shared with Object. But if you set autoloads directly on Module, they # appear on multiple classes. So just skip, Object will take care of those. next if mod == Module yield mod, entry.name, entry.target_path end end @autoloaded_paths = {} @interceptor_files_by_path = {} end |
#wrap_require(requested_path, absolute_path_found) ⇒ Object
&block
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/deep_cover/autoload_tracker.rb', line 48 def wrap_require(requested_path, absolute_path_found) # &block entries = entries_for_target(requested_path, absolute_path_found) begin entries.each do |entry| mod = entry.mod_if_available next unless mod mod.autoload_without_deep_cover(entry.name, already_loaded_feature) end yield ensure entries = entries_for_target(requested_path, absolute_path_found) entries.each do |entry| mod = entry.mod_if_available next unless mod # Putting the autoloads back back since we couldn't complete the require mod.autoload_without_deep_cover(entry.name, entry.interceptor_path) end end end |