Module: Ivar
- Defined in:
- lib/ivar.rb,
lib/ivar/macros.rb,
lib/ivar/checked.rb,
lib/ivar/version.rb,
lib/ivar/manifest.rb,
lib/ivar/policies.rb,
lib/ivar/validation.rb,
lib/ivar/declaration.rb,
lib/ivar/check_policy.rb,
lib/ivar/project_root.rb,
lib/ivar/check_all_manager.rb,
lib/ivar/explicit_declaration.rb,
lib/ivar/checked/class_methods.rb,
lib/ivar/targeted_prism_analysis.rb,
lib/ivar/checked/instance_methods.rb,
lib/ivar/explicit_keyword_declaration.rb,
lib/ivar/explicit_positional_declaration.rb
Defined Under Namespace
Modules: CheckPolicy, Checked, Macros, Validation Classes: CheckAllManager, Declaration, ExplicitDeclaration, ExplicitKeywordDeclaration, ExplicitPositionalDeclaration, IvarCollector, LogPolicy, Manifest, MethodTargetedInstanceVariableReferenceVisitor, NonePolicy, Policy, ProjectRoot, RaisePolicy, TargetedPrismAnalysis, WarnOncePolicy, WarnPolicy
Constant Summary collapse
- MUTEX =
Mutex.new
- PROJECT_ROOT_FINDER =
ProjectRoot.new
- CHECK_ALL_MANAGER =
CheckAllManager.new
- INTERNAL_IVAR_PREFIX =
Pattern for internal instance variables
"@__ivar_"- VERSION =
"0.4.7"- POLICY_CLASSES =
Map of policy symbols to policy classes
{ warn: WarnPolicy, warn_once: WarnOncePolicy, raise: RaisePolicy, log: LogPolicy, none: NonePolicy }.freeze
Class Method Summary collapse
-
.check_all(&block) ⇒ void
Enables automatic inclusion of Ivar::Checked in all classes and modules defined within the project root.
-
.check_policy ⇒ Symbol
Get the default check policy.
-
.check_policy=(policy) ⇒ Object
Set the default check policy.
-
.class_checked?(klass) ⇒ Boolean
Checks if a class has been validated already Thread-safe: Read-only operation.
-
.clear_analysis_cache ⇒ Object
For testing purposes - allows clearing the cache Thread-safe: Write operation protected by mutex.
-
.disable_check_all ⇒ void
Disables automatic inclusion of Ivar::Checked in classes and modules.
-
.get_analysis(klass) ⇒ Object
Returns a cached analysis for the given class or module Creates a new analysis if one doesn’t exist in the cache Thread-safe: Multiple readers are allowed, but writers block all other access.
- .get_ancestral_analyses(klass) ⇒ Object
-
.get_manifest(klass, create: true) ⇒ Manifest?
Get or create a manifest for a class or module.
-
.get_or_create_manifest(klass) ⇒ Manifest
Alias for get_manifest that makes it clearer that it may create a manifest.
-
.get_policy(policy, **options) ⇒ Policy
Get a policy instance from a symbol or policy object.
-
.get_stashed_method(klass, method_name) ⇒ UnboundMethod?
Gets a method from the stash or returns nil if not found.
-
.internal_ivar?(ivar_name) ⇒ Boolean
Checks if an instance variable name is an internal variable.
-
.known_internal_ivars ⇒ Array<Symbol>
Returns a list of known internal instance variables.
-
.manifest_exists?(klass) ⇒ Boolean
Check if a manifest exists for a class or module.
-
.mark_class_checked(klass) ⇒ Object
Marks a class as having been checked Thread-safe: Write operation protected by mutex.
- .maybe_get_analysis(klass) ⇒ Object
-
.project_root(caller_location = nil) ⇒ String
Determines the project root directory based on the caller’s location Delegates to ProjectRoot class.
- .project_root=(explicit_root) ⇒ Object
-
.stash_method(klass, method_name) ⇒ UnboundMethod?
Stashes a method implementation for a class.
Class Method Details
.check_all(&block) ⇒ void
This method returns an undefined value.
Enables automatic inclusion of Ivar::Checked in all classes and modules defined within the project root.
154 155 156 157 |
# File 'lib/ivar.rb', line 154 def self.check_all(&block) root = project_root CHECK_ALL_MANAGER.enable(root, &block) end |
.check_policy ⇒ Symbol
Get the default check policy
126 127 128 |
# File 'lib/ivar.rb', line 126 def self.check_policy @default_check_policy end |
.check_policy=(policy) ⇒ Object
Set the default check policy
132 133 134 |
# File 'lib/ivar.rb', line 132 def self.check_policy=(policy) MUTEX.synchronize { @default_check_policy = policy } end |
.class_checked?(klass) ⇒ Boolean
Checks if a class has been validated already Thread-safe: Read-only operation
75 76 77 |
# File 'lib/ivar.rb', line 75 def self.class_checked?(klass) MUTEX.synchronize { @checked_classes.key?(klass) } end |
.clear_analysis_cache ⇒ Object
For testing purposes - allows clearing the cache Thread-safe: Write operation protected by mutex
88 89 90 91 92 93 94 95 |
# File 'lib/ivar.rb', line 88 def self.clear_analysis_cache MUTEX.synchronize do @analysis_cache.clear @checked_classes.clear @manifest_registry.clear end PROJECT_ROOT_FINDER.clear_cache end |
.disable_check_all ⇒ void
This method returns an undefined value.
Disables automatic inclusion of Ivar::Checked in classes and modules.
161 162 163 |
# File 'lib/ivar.rb', line 161 def self.disable_check_all CHECK_ALL_MANAGER.disable end |
.get_analysis(klass) ⇒ Object
Returns a cached analysis for the given class or module Creates a new analysis if one doesn’t exist in the cache Thread-safe: Multiple readers are allowed, but writers block all other access
63 64 65 66 67 68 69 |
# File 'lib/ivar.rb', line 63 def self.get_analysis(klass) return @analysis_cache[klass] if @analysis_cache.key?(klass) MUTEX.synchronize do @analysis_cache[klass] ||= TargetedPrismAnalysis.new(klass) end end |
.get_ancestral_analyses(klass) ⇒ Object
48 49 50 51 52 |
# File 'lib/ivar.rb', line 48 def self.get_ancestral_analyses(klass) klass .ancestors.filter_map { |ancestor| maybe_get_analysis(ancestor) } .reverse end |
.get_manifest(klass, create: true) ⇒ Manifest?
Get or create a manifest for a class or module
101 102 103 104 105 106 107 108 |
# File 'lib/ivar.rb', line 101 def self.get_manifest(klass, create: true) return @manifest_registry[klass] if @manifest_registry.key?(klass) return nil unless create MUTEX.synchronize do @manifest_registry[klass] ||= Manifest.new(klass) end end |
.get_or_create_manifest(klass) ⇒ Manifest
Alias for get_manifest that makes it clearer that it may create a manifest
113 114 115 |
# File 'lib/ivar.rb', line 113 def self.get_or_create_manifest(klass) get_manifest(klass, create: true) end |
.get_policy(policy, **options) ⇒ Policy
Get a policy instance from a symbol or policy object
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/ivar/policies.rb', line 142 def self.get_policy(policy, **) return policy if policy.is_a?(Policy) # Handle the case where policy is an array with [policy_name, options] if policy.is_a?(Array) && policy.size == 2 && policy[1].is_a?(Hash) policy_name, = policy policy_class = POLICY_CLASSES[policy_name] raise ArgumentError, "Unknown policy: #{policy_name}" unless policy_class return policy_class.new(**) end policy_class = POLICY_CLASSES[policy] raise ArgumentError, "Unknown policy: #{policy}" unless policy_class policy_class.new(**) end |
.get_stashed_method(klass, method_name) ⇒ UnboundMethod?
Gets a method from the stash or returns nil if not found
169 170 171 |
# File 'lib/ivar.rb', line 169 def self.get_stashed_method(klass, method_name) (klass.instance_variable_get(:@__ivar_method_impl_stash) || {})[method_name] end |
.internal_ivar?(ivar_name) ⇒ Boolean
Checks if an instance variable name is an internal variable
33 34 35 |
# File 'lib/ivar.rb', line 33 def self.internal_ivar?(ivar_name) ivar_name.to_s.start_with?(INTERNAL_IVAR_PREFIX) end |
.known_internal_ivars ⇒ Array<Symbol>
Returns a list of known internal instance variables
39 40 41 42 43 44 45 46 |
# File 'lib/ivar.rb', line 39 def self.known_internal_ivars [ :@__ivar_check_policy, :@__ivar_initialized_vars, :@__ivar_method_impl_stash, :@__ivar_skip_init ] end |
.manifest_exists?(klass) ⇒ Boolean
Check if a manifest exists for a class or module
120 121 122 |
# File 'lib/ivar.rb', line 120 def self.manifest_exists?(klass) @manifest_registry.key?(klass) end |
.mark_class_checked(klass) ⇒ Object
Marks a class as having been checked Thread-safe: Write operation protected by mutex
82 83 84 |
# File 'lib/ivar.rb', line 82 def self.mark_class_checked(klass) MUTEX.synchronize { @checked_classes[klass] = true } end |
.maybe_get_analysis(klass) ⇒ Object
54 55 56 57 58 |
# File 'lib/ivar.rb', line 54 def self.maybe_get_analysis(klass) if klass.include?(Validation) get_analysis(klass) end end |
.project_root(caller_location = nil) ⇒ String
Determines the project root directory based on the caller’s location Delegates to ProjectRoot class
144 145 146 |
# File 'lib/ivar.rb', line 144 def self.project_root(caller_location = nil) @project_root ||= PROJECT_ROOT_FINDER.find(caller_location) end |
.project_root=(explicit_root) ⇒ Object
136 137 138 |
# File 'lib/ivar.rb', line 136 def self.project_root=(explicit_root) @project_root = explicit_root end |
.stash_method(klass, method_name) ⇒ UnboundMethod?
Stashes a method implementation for a class
177 178 179 180 181 182 183 184 |
# File 'lib/ivar.rb', line 177 def self.stash_method(klass, method_name) return nil unless klass.method_defined?(method_name) || klass.private_method_defined?(method_name) method_impl = klass.instance_method(method_name) stash = klass.instance_variable_get(:@__ivar_method_impl_stash) || klass.instance_variable_set(:@__ivar_method_impl_stash, {}) stash[method_name] = method_impl end |