ivar 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.augment-guidelines +10 -0
- data/.devcontainer/Dockerfile +21 -0
- data/.devcontainer/devcontainer.json +22 -0
- data/.standard.yml +3 -0
- data/.vscode/extensions.json +8 -0
- data/.vscode/settings.json +14 -0
- data/CHANGELOG.md +9 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/LICENSE.txt +21 -0
- data/README.md +343 -0
- data/Rakefile +14 -0
- data/examples/sandwich_inheritance.rb +33 -0
- data/examples/sandwich_with_checked.rb +23 -0
- data/examples/sandwich_with_checked_once.rb +29 -0
- data/examples/sandwich_with_ivar_block.rb +43 -0
- data/examples/sandwich_with_ivar_macro.rb +37 -0
- data/examples/sandwich_with_kwarg.rb +45 -0
- data/ivar.gemspec +49 -0
- data/lib/ivar/auto_check.rb +77 -0
- data/lib/ivar/checked.rb +40 -0
- data/lib/ivar/macros.rb +123 -0
- data/lib/ivar/policies.rb +147 -0
- data/lib/ivar/prism_analysis.rb +102 -0
- data/lib/ivar/validation.rb +55 -0
- data/lib/ivar/version.rb +5 -0
- data/lib/ivar.rb +53 -0
- data/sig/ivar.rbs +4 -0
- data/test_file.rb +1 -0
- metadata +98 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "did_you_mean"
|
4
|
+
|
5
|
+
module Ivar
|
6
|
+
# Provides validation for instance variables
|
7
|
+
module Validation
|
8
|
+
# Checks instance variables against class analysis
|
9
|
+
# @param add [Array<Symbol>] Additional instance variables to allow
|
10
|
+
# @param policy [Symbol, Policy] The policy to use for handling unknown variables
|
11
|
+
def check_ivars(add: [], policy: nil)
|
12
|
+
# Get the policy to use
|
13
|
+
policy ||= get_check_policy
|
14
|
+
|
15
|
+
# Get the class analysis from the cache
|
16
|
+
analysis = Ivar.get_analysis(self.class)
|
17
|
+
|
18
|
+
# Get all instance variables defined in the current object
|
19
|
+
# These are the ones the user has explicitly defined before calling check_ivars
|
20
|
+
defined_ivars = instance_variables.map(&:to_sym)
|
21
|
+
|
22
|
+
# Add any additional allowed variables
|
23
|
+
allowed_ivars = defined_ivars + add
|
24
|
+
|
25
|
+
# Get all instance variable references from the analysis
|
26
|
+
# This includes location information for each reference
|
27
|
+
references = analysis.ivar_references
|
28
|
+
|
29
|
+
# Find references to unknown variables (those not in allowed_ivars)
|
30
|
+
unknown_refs = references.reject { |ref| allowed_ivars.include?(ref[:name]) }
|
31
|
+
|
32
|
+
# Handle unknown variables according to the policy
|
33
|
+
policy_instance = Ivar.get_policy(policy)
|
34
|
+
policy_instance.handle_unknown_ivars(unknown_refs, self.class, allowed_ivars)
|
35
|
+
end
|
36
|
+
|
37
|
+
# For backward compatibility - delegates to check_ivars with warn_once policy
|
38
|
+
# @param add [Array<Symbol>] Additional instance variables to allow
|
39
|
+
def check_ivars_once(add: [])
|
40
|
+
check_ivars(add: add, policy: :warn_once)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# Get the check policy for this instance
|
46
|
+
# @return [Symbol, Policy] The check policy
|
47
|
+
def get_check_policy
|
48
|
+
# If the class has an ivar_check_policy method, use that
|
49
|
+
return self.class.ivar_check_policy if self.class.respond_to?(:ivar_check_policy)
|
50
|
+
|
51
|
+
# Otherwise, use the global default
|
52
|
+
Ivar.check_policy
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/ivar/version.rb
ADDED
data/lib/ivar.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "ivar/version"
|
4
|
+
require_relative "ivar/prism_analysis"
|
5
|
+
require_relative "ivar/policies"
|
6
|
+
require_relative "ivar/validation"
|
7
|
+
require_relative "ivar/macros"
|
8
|
+
require_relative "ivar/auto_check"
|
9
|
+
require "prism"
|
10
|
+
require "did_you_mean"
|
11
|
+
|
12
|
+
module Ivar
|
13
|
+
@analysis_cache = {}
|
14
|
+
@checked_classes = {}
|
15
|
+
@default_check_policy = :warn
|
16
|
+
|
17
|
+
# Returns a cached analysis for the given class or module
|
18
|
+
# Creates a new analysis if one doesn't exist in the cache
|
19
|
+
def self.get_analysis(klass)
|
20
|
+
@analysis_cache[klass] ||= PrismAnalysis.new(klass)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Checks if a class has been validated already
|
24
|
+
# @param klass [Class] The class to check
|
25
|
+
# @return [Boolean] Whether the class has been validated
|
26
|
+
def self.class_checked?(klass)
|
27
|
+
@checked_classes.key?(klass)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Marks a class as having been checked
|
31
|
+
# @param klass [Class] The class to mark as checked
|
32
|
+
def self.mark_class_checked(klass)
|
33
|
+
@checked_classes[klass] = true
|
34
|
+
end
|
35
|
+
|
36
|
+
# For testing purposes - allows clearing the cache
|
37
|
+
def self.clear_analysis_cache
|
38
|
+
@analysis_cache.clear
|
39
|
+
@checked_classes.clear
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get the default check policy
|
43
|
+
# @return [Symbol] The default check policy
|
44
|
+
def self.check_policy
|
45
|
+
@default_check_policy
|
46
|
+
end
|
47
|
+
|
48
|
+
# Set the default check policy
|
49
|
+
# @param policy [Symbol, Policy] The default check policy
|
50
|
+
def self.check_policy=(policy)
|
51
|
+
@default_check_policy = policy
|
52
|
+
end
|
53
|
+
end
|
data/sig/ivar.rbs
ADDED
data/test_file.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
class MockClass; end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ivar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Avdi Grimm
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: prism
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '1.2'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '1.2'
|
26
|
+
description: |
|
27
|
+
Ruby instance variables are so convenient - you don't even need to declare them!
|
28
|
+
But... they are also dangerous, because a mispelled variable name results in `nil`
|
29
|
+
instead of an error.
|
30
|
+
|
31
|
+
Why not have the best of both worlds? Ivar lets you use plain-old instance variables,
|
32
|
+
and automatically checks for typos.
|
33
|
+
|
34
|
+
Ivar waits until an instance is created to do the checking, then uses Prism to look
|
35
|
+
for variables that don't match what was set in initialization. So it's a little bit
|
36
|
+
dynamic, a little bit static. It doesn't encumber your instance variable reads and
|
37
|
+
writes with any extra checking. And with the `:warn_once` policy, it won't overwhelm
|
38
|
+
you with output.
|
39
|
+
email:
|
40
|
+
- avdi@avdi.codes
|
41
|
+
executables: []
|
42
|
+
extensions: []
|
43
|
+
extra_rdoc_files: []
|
44
|
+
files:
|
45
|
+
- ".augment-guidelines"
|
46
|
+
- ".devcontainer/Dockerfile"
|
47
|
+
- ".devcontainer/devcontainer.json"
|
48
|
+
- ".standard.yml"
|
49
|
+
- ".vscode/extensions.json"
|
50
|
+
- ".vscode/settings.json"
|
51
|
+
- CHANGELOG.md
|
52
|
+
- CODE_OF_CONDUCT.md
|
53
|
+
- LICENSE.txt
|
54
|
+
- README.md
|
55
|
+
- Rakefile
|
56
|
+
- examples/sandwich_inheritance.rb
|
57
|
+
- examples/sandwich_with_checked.rb
|
58
|
+
- examples/sandwich_with_checked_once.rb
|
59
|
+
- examples/sandwich_with_ivar_block.rb
|
60
|
+
- examples/sandwich_with_ivar_macro.rb
|
61
|
+
- examples/sandwich_with_kwarg.rb
|
62
|
+
- ivar.gemspec
|
63
|
+
- lib/ivar.rb
|
64
|
+
- lib/ivar/auto_check.rb
|
65
|
+
- lib/ivar/checked.rb
|
66
|
+
- lib/ivar/macros.rb
|
67
|
+
- lib/ivar/policies.rb
|
68
|
+
- lib/ivar/prism_analysis.rb
|
69
|
+
- lib/ivar/validation.rb
|
70
|
+
- lib/ivar/version.rb
|
71
|
+
- sig/ivar.rbs
|
72
|
+
- test_file.rb
|
73
|
+
homepage: https://github.com/avdi/ivar
|
74
|
+
licenses:
|
75
|
+
- MIT
|
76
|
+
metadata:
|
77
|
+
allowed_push_host: https://rubygems.org
|
78
|
+
homepage_uri: https://github.com/avdi/ivar
|
79
|
+
source_code_uri: https://github.com/avdi/ivar
|
80
|
+
changelog_uri: https://github.com/avdi/ivar/blob/main/CHANGELOG.md
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 3.4.0
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubygems_version: 3.6.7
|
96
|
+
specification_version: 4
|
97
|
+
summary: Automatically check instance variables for typos.
|
98
|
+
test_files: []
|