ivar 0.2.0 → 0.4.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 +4 -4
- data/.augment-guidelines +5 -3
- data/.devcontainer/devcontainer.json +28 -20
- data/.devcontainer/post-create.sh +18 -0
- data/.editorconfig +35 -0
- data/.rubocop.yml +6 -0
- data/.standard.yml +1 -1
- data/.vscode/extensions.json +3 -1
- data/.vscode/launch.json +25 -0
- data/.vscode/settings.json +38 -2
- data/CHANGELOG.md +83 -1
- data/README.md +272 -207
- data/Rakefile +1 -1
- data/VERSION.md +44 -0
- data/examples/check_all_block_example.rb +84 -0
- data/examples/check_all_example.rb +42 -0
- data/examples/inheritance_with_kwarg_init.rb +156 -0
- data/examples/inheritance_with_positional_init.rb +142 -0
- data/examples/mixed_positional_and_kwarg_init.rb +125 -0
- data/examples/require_check_all_example.rb +23 -0
- data/examples/sandwich_inheritance.rb +1 -1
- data/examples/sandwich_with_accessors.rb +78 -0
- data/examples/sandwich_with_block_values.rb +54 -0
- data/examples/sandwich_with_checked.rb +0 -1
- data/examples/sandwich_with_checked_once.rb +0 -1
- data/examples/sandwich_with_initial_values.rb +52 -0
- data/examples/sandwich_with_ivar_block.rb +6 -9
- data/examples/sandwich_with_ivar_macro.rb +4 -4
- data/examples/sandwich_with_kwarg_init.rb +78 -0
- data/examples/sandwich_with_positional_init.rb +50 -0
- data/examples/sandwich_with_shared_values.rb +54 -0
- data/hooks/README.md +42 -0
- data/hooks/install.sh +12 -0
- data/hooks/pre-commit +54 -0
- data/ivar.gemspec +5 -4
- data/lib/ivar/check_all.rb +7 -0
- data/lib/ivar/check_all_manager.rb +72 -0
- data/lib/ivar/check_policy.rb +29 -0
- data/lib/ivar/checked/class_methods.rb +19 -0
- data/lib/ivar/checked/instance_methods.rb +35 -0
- data/lib/ivar/checked.rb +17 -24
- data/lib/ivar/declaration.rb +30 -0
- data/lib/ivar/explicit_declaration.rb +56 -0
- data/lib/ivar/explicit_keyword_declaration.rb +24 -0
- data/lib/ivar/explicit_positional_declaration.rb +19 -0
- data/lib/ivar/macros.rb +48 -111
- data/lib/ivar/manifest.rb +124 -0
- data/lib/ivar/policies.rb +13 -1
- data/lib/ivar/project_root.rb +59 -0
- data/lib/ivar/targeted_prism_analysis.rb +144 -0
- data/lib/ivar/validation.rb +6 -29
- data/lib/ivar/version.rb +1 -1
- data/lib/ivar.rb +141 -9
- data/script/console +11 -0
- data/script/de-lint +2 -0
- data/script/de-lint-unsafe +2 -0
- data/script/lint +2 -0
- data/script/release +134 -0
- data/script/setup +8 -0
- data/script/test +2 -0
- metadata +41 -5
- data/examples/sandwich_with_kwarg.rb +0 -45
- data/lib/ivar/auto_check.rb +0 -77
- data/lib/ivar/prism_analysis.rb +0 -102
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "ivar"
|
4
|
-
|
5
|
-
class SandwichWithKwarg
|
6
|
-
include Ivar::Checked
|
7
|
-
|
8
|
-
# Pre-declare instance variables to be initialized from keyword arguments
|
9
|
-
ivar kwarg: [:@bread, :@cheese, :@condiments]
|
10
|
-
|
11
|
-
def initialize(pickles: false, side: nil)
|
12
|
-
# Note: @bread, @cheese, and @condiments are already set from keyword arguments
|
13
|
-
# We only need to handle the remaining keyword arguments
|
14
|
-
@pickles = pickles
|
15
|
-
@side = side
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_s
|
19
|
-
result = "A #{@bread} sandwich with #{@cheese}"
|
20
|
-
result += " and #{@condiments.join(", ")}" unless @condiments.empty?
|
21
|
-
result += " with pickles" if @pickles
|
22
|
-
result += " and a side of #{@side}" if @side
|
23
|
-
result
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# Create a sandwich with keyword arguments
|
28
|
-
sandwich = SandwichWithKwarg.new(
|
29
|
-
bread: "wheat",
|
30
|
-
cheese: "muenster",
|
31
|
-
condiments: ["mayo", "mustard"],
|
32
|
-
side: "chips"
|
33
|
-
)
|
34
|
-
|
35
|
-
puts sandwich # Outputs: A wheat sandwich with muenster and mayo, mustard and a side of chips
|
36
|
-
|
37
|
-
# Create another sandwich with different keyword arguments
|
38
|
-
sandwich2 = SandwichWithKwarg.new(
|
39
|
-
bread: "rye",
|
40
|
-
cheese: "swiss",
|
41
|
-
condiments: ["mustard"],
|
42
|
-
pickles: true
|
43
|
-
)
|
44
|
-
|
45
|
-
puts sandwich2 # Outputs: A rye sandwich with swiss and mustard with pickles
|
data/lib/ivar/auto_check.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "validation"
|
4
|
-
require_relative "macros"
|
5
|
-
|
6
|
-
module Ivar
|
7
|
-
# Module for adding ivar_check_policy to classes
|
8
|
-
module CheckPolicy
|
9
|
-
# Set the check policy for this class
|
10
|
-
# @param policy [Symbol, Policy] The check policy
|
11
|
-
# @return [Symbol, Policy] The check policy
|
12
|
-
def ivar_check_policy(policy = nil, **options)
|
13
|
-
if policy.nil?
|
14
|
-
# Getter - return the current policy
|
15
|
-
@__ivar_check_policy || Ivar.check_policy
|
16
|
-
else
|
17
|
-
# Setter - set the policy
|
18
|
-
@__ivar_check_policy = options.empty? ? policy : [policy, options]
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Hook method called when the module is included
|
23
|
-
def inherited(subclass)
|
24
|
-
super
|
25
|
-
# Copy the check policy to the subclass
|
26
|
-
subclass.instance_variable_set(:@__ivar_check_policy, @__ivar_check_policy)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Provides automatic validation for instance variables
|
31
|
-
# When included, automatically calls check_ivars after initialization
|
32
|
-
module Checked
|
33
|
-
# When this module is included in a class, it extends the class
|
34
|
-
# with ClassMethods and includes the Validation module
|
35
|
-
def self.included(base)
|
36
|
-
base.include(Validation)
|
37
|
-
base.include(PreInitializeIvars)
|
38
|
-
base.extend(ClassMethods)
|
39
|
-
base.extend(CheckPolicy)
|
40
|
-
base.extend(Macros)
|
41
|
-
base.prepend(InstanceMethods)
|
42
|
-
|
43
|
-
# Set default policy for Checked to :warn
|
44
|
-
base.ivar_check_policy(:warn)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Class methods added to the including class
|
48
|
-
module ClassMethods
|
49
|
-
# Hook method called when the module is included
|
50
|
-
def inherited(subclass)
|
51
|
-
super
|
52
|
-
# Ensure subclasses also get the initialize wrapper
|
53
|
-
subclass.prepend(Ivar::Checked::InstanceMethods)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Instance methods that will be prepended to the including class
|
58
|
-
module InstanceMethods
|
59
|
-
# Wrap the initialize method to automatically call check_ivars
|
60
|
-
def initialize(*args, **kwargs, &block)
|
61
|
-
# Initialize pre-declared instance variables
|
62
|
-
initialize_pre_declared_ivars
|
63
|
-
# Execute the initialization block if provided
|
64
|
-
execute_ivar_init_block
|
65
|
-
|
66
|
-
# Process keyword arguments
|
67
|
-
remaining_kwargs = initialize_from_kwargs(kwargs)
|
68
|
-
|
69
|
-
# Call the original initialize method with remaining arguments
|
70
|
-
super(*args, **remaining_kwargs, &block)
|
71
|
-
|
72
|
-
# Automatically check instance variables
|
73
|
-
check_ivars
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
data/lib/ivar/prism_analysis.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "prism"
|
4
|
-
|
5
|
-
module Ivar
|
6
|
-
# Analyzes a class to find all instance variables using Prism
|
7
|
-
class PrismAnalysis
|
8
|
-
attr_reader :ivars
|
9
|
-
|
10
|
-
def initialize(klass)
|
11
|
-
@klass = klass
|
12
|
-
@references = nil
|
13
|
-
collect_references
|
14
|
-
@ivars = unique_ivar_names
|
15
|
-
end
|
16
|
-
|
17
|
-
# Returns a list of hashes each representing a code reference to an ivar
|
18
|
-
# Each hash includes var name, path, line number, and column number
|
19
|
-
def ivar_references
|
20
|
-
@references
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def collect_references
|
26
|
-
source_files = collect_source_files
|
27
|
-
@references = []
|
28
|
-
|
29
|
-
source_files.each do |file_path|
|
30
|
-
code = File.read(file_path)
|
31
|
-
result = Prism.parse(code)
|
32
|
-
visitor = IvarReferenceVisitor.new(file_path)
|
33
|
-
result.value.accept(visitor)
|
34
|
-
@references.concat(visitor.references)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def unique_ivar_names
|
39
|
-
@references.map { |ref| ref[:name] }.uniq.sort
|
40
|
-
end
|
41
|
-
|
42
|
-
def collect_source_files
|
43
|
-
# Get all instance methods
|
44
|
-
instance_methods = @klass.instance_methods(false) | @klass.private_instance_methods(false)
|
45
|
-
|
46
|
-
# Collect source files for all methods
|
47
|
-
source_files = Set.new
|
48
|
-
instance_methods.each do |method_name|
|
49
|
-
next unless @klass.instance_method(method_name).source_location
|
50
|
-
|
51
|
-
source_files << @klass.instance_method(method_name).source_location.first
|
52
|
-
end
|
53
|
-
|
54
|
-
source_files
|
55
|
-
end
|
56
|
-
|
57
|
-
# Visitor that collects instance variable references with location information
|
58
|
-
class IvarReferenceVisitor < Prism::Visitor
|
59
|
-
attr_reader :references
|
60
|
-
|
61
|
-
def initialize(file_path)
|
62
|
-
super()
|
63
|
-
@file_path = file_path
|
64
|
-
@references = []
|
65
|
-
end
|
66
|
-
|
67
|
-
def visit_instance_variable_read_node(node)
|
68
|
-
add_reference(node)
|
69
|
-
true
|
70
|
-
end
|
71
|
-
|
72
|
-
def visit_instance_variable_write_node(node)
|
73
|
-
add_reference(node)
|
74
|
-
true
|
75
|
-
end
|
76
|
-
|
77
|
-
def visit_instance_variable_operator_write_node(node)
|
78
|
-
add_reference(node)
|
79
|
-
true
|
80
|
-
end
|
81
|
-
|
82
|
-
def visit_instance_variable_target_node(node)
|
83
|
-
add_reference(node)
|
84
|
-
true
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
|
89
|
-
def add_reference(node)
|
90
|
-
location = node.location
|
91
|
-
reference = {
|
92
|
-
name: node.name.to_sym,
|
93
|
-
path: @file_path,
|
94
|
-
line: location.start_line,
|
95
|
-
column: location.start_column
|
96
|
-
}
|
97
|
-
|
98
|
-
@references << reference
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|