strict 0.0.0 → 1.1.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +14 -2
  3. data/Gemfile.lock +19 -2
  4. data/README.md +165 -6
  5. data/lib/strict/accessor/attributes.rb +15 -0
  6. data/lib/strict/accessor/module.rb +45 -0
  7. data/lib/strict/assignment_error.rb +25 -0
  8. data/lib/strict/attribute.rb +71 -0
  9. data/lib/strict/attributes/class.rb +17 -0
  10. data/lib/strict/attributes/coercer.rb +32 -0
  11. data/lib/strict/attributes/configuration.rb +46 -0
  12. data/lib/strict/attributes/dsl.rb +43 -0
  13. data/lib/strict/attributes/instance.rb +68 -0
  14. data/lib/strict/coercers/array.rb +22 -0
  15. data/lib/strict/coercers/hash.rb +34 -0
  16. data/lib/strict/dsl/coercible.rb +14 -0
  17. data/lib/strict/dsl/validatable.rb +28 -0
  18. data/lib/strict/implementation_does_not_conform_error.rb +88 -0
  19. data/lib/strict/initialization_error.rb +57 -0
  20. data/lib/strict/interface.rb +21 -0
  21. data/lib/strict/interfaces/instance.rb +54 -0
  22. data/lib/strict/method.rb +72 -0
  23. data/lib/strict/method_call_error.rb +72 -0
  24. data/lib/strict/method_definition_error.rb +46 -0
  25. data/lib/strict/method_return_error.rb +25 -0
  26. data/lib/strict/methods/configuration.rb +14 -0
  27. data/lib/strict/methods/dsl.rb +56 -0
  28. data/lib/strict/methods/module.rb +26 -0
  29. data/lib/strict/methods/verifiable_method.rb +158 -0
  30. data/lib/strict/object.rb +9 -0
  31. data/lib/strict/parameter.rb +63 -0
  32. data/lib/strict/reader/attributes.rb +15 -0
  33. data/lib/strict/reader/module.rb +27 -0
  34. data/lib/strict/return.rb +28 -0
  35. data/lib/strict/validators/all_of.rb +24 -0
  36. data/lib/strict/validators/any_of.rb +24 -0
  37. data/lib/strict/validators/anything.rb +20 -0
  38. data/lib/strict/validators/array_of.rb +24 -0
  39. data/lib/strict/validators/boolean.rb +20 -0
  40. data/lib/strict/validators/hash_of.rb +25 -0
  41. data/lib/strict/validators/range_of.rb +24 -0
  42. data/lib/strict/value.rb +22 -0
  43. data/lib/strict/version.rb +1 -1
  44. data/lib/strict.rb +1 -0
  45. data/strict.gemspec +41 -0
  46. metadata +97 -2
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module Strict
6
+ module Methods
7
+ class VerifiableMethod # rubocop:disable Metrics/ClassLength
8
+ extend Forwardable
9
+
10
+ class UnknownParameterError < Error
11
+ attr_reader :parameter_name
12
+
13
+ def initialize(parameter_name:)
14
+ super(message_from(parameter_name:))
15
+
16
+ @parameter_name = parameter_name
17
+ end
18
+
19
+ private
20
+
21
+ def message_from(parameter_name:)
22
+ "Strict tried to find a parameter named #{parameter_name} but was unable. " \
23
+ "It's likely this in an internal bug, feel free to open an issue at #{Strict::ISSUE_TRACKER} for help."
24
+ end
25
+ end
26
+
27
+ def_delegator :method, :name
28
+
29
+ attr_reader :parameters, :returns
30
+
31
+ def initialize(method:, parameters:, returns:, instance:)
32
+ @method = method
33
+ @parameters = parameters
34
+ @parameters_index = parameters.to_h { |p| [p.name, p] }
35
+ @returns = returns
36
+ @instance = instance
37
+ end
38
+
39
+ def to_s
40
+ "#{method.owner}#{separator}#{name}"
41
+ end
42
+
43
+ def verify_definition!
44
+ expected_parameters = Set.new(parameters.map(&:name))
45
+ defined_parameters = Set.new(method.parameters.filter_map { |kind, name| name unless kind == :block })
46
+ return if expected_parameters == defined_parameters
47
+
48
+ missing_parameters = expected_parameters - defined_parameters
49
+ additional_parameters = defined_parameters - expected_parameters
50
+ raise Strict::MethodDefinitionError.new(verifiable_method: self, missing_parameters:, additional_parameters:)
51
+ end
52
+
53
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/BlockLength
54
+ # TODO(kkt): clean this up- it's late, though, and the tests are passing
55
+ def verify_parameters!(*args, **kwargs)
56
+ invalid_parameters = nil
57
+ missing_parameters = nil
58
+
59
+ positional_arguments = []
60
+ keyword_arguments = {}
61
+
62
+ # TODO(kkt): doesn't handle oddly sorted optional positional parameters like def foo(opt = nil, req)
63
+ method.parameters.each do |kind, name|
64
+ case kind
65
+ when POSITIONAL
66
+ parameter_kind = :positional
67
+ value = args.any? ? args.shift : NOT_PROVIDED
68
+ when REST
69
+ parameter_kind = :rest
70
+ value = [*args]
71
+ args.clear
72
+ when KEYWORD
73
+ parameter_kind = :keyword
74
+ value = kwargs.key?(name) ? kwargs.delete(name) : NOT_PROVIDED
75
+ when KEYREST
76
+ parameter_kind = :keyrest
77
+ value = { **kwargs }
78
+ kwargs.clear
79
+ end
80
+ next unless parameter_kind
81
+
82
+ parameter = parameter_named!(name)
83
+ if value.equal?(NOT_PROVIDED) && parameter.optional?
84
+ value = parameter.default_generator.call
85
+ elsif value.equal?(NOT_PROVIDED)
86
+ missing_parameters ||= []
87
+ missing_parameters << parameter.name
88
+ next
89
+ end
90
+
91
+ value = parameter.coerce(value)
92
+ if parameter.valid?(value)
93
+ case parameter_kind
94
+ when :positional
95
+ positional_arguments << value
96
+ when :rest
97
+ positional_arguments.concat(value)
98
+ when :keyword
99
+ keyword_arguments[name] = value
100
+ when :keyrest
101
+ keyword_arguments.merge!(value)
102
+ end
103
+ else
104
+ invalid_parameters ||= {}
105
+ invalid_parameters[parameter] = value
106
+ end
107
+ end
108
+
109
+ if args.empty? && kwargs.empty? && invalid_parameters.nil? && missing_parameters.nil?
110
+ [positional_arguments, keyword_arguments]
111
+ else
112
+ raise Strict::MethodCallError.new(
113
+ verifiable_method: self,
114
+ remaining_args: args,
115
+ remaining_kwargs: kwargs,
116
+ invalid_parameters:,
117
+ missing_parameters:
118
+ )
119
+ end
120
+ end
121
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/BlockLength
122
+
123
+ def verify_returns!(value)
124
+ value = returns.coerce(value)
125
+ return if returns.valid?(value)
126
+
127
+ raise Strict::MethodReturnError.new(verifiable_method: self, value:)
128
+ end
129
+
130
+ private
131
+
132
+ POSITIONAL = Set.new(%i[req opt])
133
+ private_constant :POSITIONAL
134
+ REST = :rest
135
+ private_constant :REST
136
+ KEYWORD = Set.new(%i[keyreq key])
137
+ private_constant :KEYWORD
138
+ KEYREST = :keyrest
139
+ private_constant :KEYREST
140
+ NOT_PROVIDED = ::Object.new.freeze
141
+ private_constant :NOT_PROVIDED
142
+
143
+ attr_reader :method, :parameters_index
144
+
145
+ def instance?
146
+ @instance
147
+ end
148
+
149
+ def separator
150
+ instance? ? "#" : "."
151
+ end
152
+
153
+ def parameter_named!(name)
154
+ parameters_index.fetch(name) { raise UnknownParameterError.new(parameter_name: name) }
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ module Object
5
+ def self.included(mod)
6
+ mod.extend(Accessor::Attributes)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ class Parameter
5
+ NOT_PROVIDED = ::Object.new.freeze
6
+
7
+ class << self
8
+ def make(name, validator = Validators::Anything.instance, coerce: false, **defaults)
9
+ unless valid_defaults?(**defaults)
10
+ raise ArgumentError, "Only one of 'default', 'default_value', or 'default_generator' can be provided"
11
+ end
12
+
13
+ new(name: name.to_sym, validator:, default_generator: make_default_generator(**defaults), coercer: coerce)
14
+ end
15
+
16
+ private
17
+
18
+ def valid_defaults?(default: NOT_PROVIDED, default_value: NOT_PROVIDED, default_generator: NOT_PROVIDED)
19
+ defaults_provided = [default, default_value, default_generator].count do |default_option|
20
+ !default_option.equal?(NOT_PROVIDED)
21
+ end
22
+
23
+ defaults_provided <= 1
24
+ end
25
+
26
+ def make_default_generator(default: NOT_PROVIDED, default_value: NOT_PROVIDED, default_generator: NOT_PROVIDED)
27
+ if !default.equal?(NOT_PROVIDED)
28
+ default.respond_to?(:call) ? default : -> { default }
29
+ elsif !default_value.equal?(NOT_PROVIDED)
30
+ -> { default_value }
31
+ elsif !default_generator.equal?(NOT_PROVIDED)
32
+ default_generator
33
+ else
34
+ NOT_PROVIDED
35
+ end
36
+ end
37
+ end
38
+
39
+ attr_reader :name, :validator, :default_generator, :coercer
40
+
41
+ def initialize(name:, validator:, default_generator:, coercer:)
42
+ @name = name.to_sym
43
+ @validator = validator
44
+ @default_generator = default_generator
45
+ @coercer = coercer
46
+ @optional = !default_generator.equal?(NOT_PROVIDED)
47
+ end
48
+
49
+ def optional?
50
+ @optional
51
+ end
52
+
53
+ def valid?(value)
54
+ validator === value
55
+ end
56
+
57
+ def coerce(value)
58
+ return value unless coercer
59
+
60
+ coercer.call(value)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ module Reader
5
+ module Attributes
6
+ def attributes(&block)
7
+ block ||= -> {}
8
+ configuration = Strict::Attributes::Dsl.run(&block)
9
+ include Module.new(configuration)
10
+ include Strict::Attributes::Instance
11
+ extend Strict::Attributes::Class
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ module Reader
5
+ class Module < ::Module
6
+ attr_reader :configuration
7
+
8
+ def initialize(configuration)
9
+ super()
10
+
11
+ @configuration = configuration
12
+ const_set(Strict::Attributes::Class::CONSTANT, configuration)
13
+ configuration.attributes.each do |attribute|
14
+ module_eval(
15
+ "def #{attribute.name} = #{attribute.instance_variable}", # def name = @instance_variable
16
+ __FILE__,
17
+ __LINE__ - 2
18
+ )
19
+ end
20
+ end
21
+
22
+ def inspect
23
+ "#<#{self.class} (#{configuration.attributes.map(&:name).join(', ')})>"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ class Return
5
+ class << self
6
+ def make(validator = Validators::Anything.instance, coerce: false)
7
+ new(validator:, coercer: coerce)
8
+ end
9
+ end
10
+
11
+ attr_reader :validator, :coercer
12
+
13
+ def initialize(validator:, coercer:)
14
+ @validator = validator
15
+ @coercer = coercer
16
+ end
17
+
18
+ def valid?(value)
19
+ validator === value
20
+ end
21
+
22
+ def coerce(value)
23
+ return value unless coercer
24
+
25
+ coercer.call(value)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ module Validators
5
+ class AllOf
6
+ attr_reader :subvalidators
7
+
8
+ def initialize(*subvalidators)
9
+ @subvalidators = subvalidators
10
+ end
11
+
12
+ def ===(value)
13
+ subvalidators.all? do |subvalidator|
14
+ subvalidator === value
15
+ end
16
+ end
17
+
18
+ def inspect
19
+ "AllOf(#{subvalidators.map(&:inspect).join(', ')})"
20
+ end
21
+ alias to_s inspect
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ module Validators
5
+ class AnyOf
6
+ attr_reader :subvalidators
7
+
8
+ def initialize(*subvalidators)
9
+ @subvalidators = subvalidators
10
+ end
11
+
12
+ def ===(value)
13
+ subvalidators.any? do |subvalidator|
14
+ subvalidator === value
15
+ end
16
+ end
17
+
18
+ def inspect
19
+ "AnyOf(#{subvalidators.map(&:inspect).join(', ')})"
20
+ end
21
+ alias to_s inspect
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ module Strict
6
+ module Validators
7
+ class Anything
8
+ include Singleton
9
+
10
+ def ===(_value)
11
+ true
12
+ end
13
+
14
+ def inspect
15
+ "Anything()"
16
+ end
17
+ alias to_s inspect
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ module Validators
5
+ class ArrayOf
6
+ attr_reader :element_validator
7
+
8
+ def initialize(element_validator)
9
+ @element_validator = element_validator
10
+ end
11
+
12
+ def ===(value)
13
+ Array === value && value.all? do |v|
14
+ element_validator === v
15
+ end
16
+ end
17
+
18
+ def inspect
19
+ "ArrayOf(#{element_validator.inspect})"
20
+ end
21
+ alias to_s inspect
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ module Strict
6
+ module Validators
7
+ class Boolean
8
+ include Singleton
9
+
10
+ def ===(value)
11
+ value.equal?(true) || value.equal?(false)
12
+ end
13
+
14
+ def inspect
15
+ "Boolean()"
16
+ end
17
+ alias to_s inspect
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ module Validators
5
+ class HashOf
6
+ attr_reader :key_validator, :value_validator
7
+
8
+ def initialize(key_validator, value_validator)
9
+ @key_validator = key_validator
10
+ @value_validator = value_validator
11
+ end
12
+
13
+ def ===(value)
14
+ Hash === value && value.all? do |k, v|
15
+ key_validator === k && value_validator === v
16
+ end
17
+ end
18
+
19
+ def inspect
20
+ "HashOf(#{key_validator.inspect} => #{value_validator.inspect})"
21
+ end
22
+ alias to_s inspect
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ module Validators
5
+ class RangeOf
6
+ attr_reader :element_validator
7
+
8
+ def initialize(element_validator)
9
+ @element_validator = element_validator
10
+ end
11
+
12
+ def ===(value)
13
+ Range === value && [value.begin, value.end].compact.all? do |v|
14
+ element_validator === v
15
+ end
16
+ end
17
+
18
+ def inspect
19
+ "RangeOf(#{element_validator.inspect})"
20
+ end
21
+ alias to_s inspect
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strict
4
+ module Value
5
+ def self.included(mod)
6
+ mod.extend(Reader::Attributes)
7
+ end
8
+
9
+ def with(**attributes)
10
+ self.class.new(**to_h.merge(attributes))
11
+ end
12
+
13
+ def eql?(other)
14
+ self.class.equal?(other.class) && to_h.eql?(other.to_h)
15
+ end
16
+ alias == eql?
17
+
18
+ def hash
19
+ [self.class, to_h].hash
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Strict
4
- VERSION = "0.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
data/lib/strict.rb CHANGED
@@ -5,4 +5,5 @@ loader = Zeitwerk::Loader.for_gem
5
5
  loader.setup
6
6
 
7
7
  module Strict
8
+ ISSUE_TRACKER = "https://github.com/kylekthompson/strict/issues"
8
9
  end
data/strict.gemspec ADDED
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/strict/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "strict"
7
+ spec.version = Strict::VERSION
8
+ spec.authors = ["Kyle Thompson"]
9
+ spec.email = ["me@kkt.dev"]
10
+
11
+ spec.summary = "Strictly define a contract for your objects and methods"
12
+ spec.homepage = "https://github.com/kylekthompson/strict"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = ">= 3.1.2"
15
+
16
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = spec.homepage
20
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
21
+ spec.metadata["rubygems_mfa_required"] = "true"
22
+
23
+ spec.files = Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
26
+ end
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_dependency "zeitwerk", "~> 2.6"
33
+ spec.add_development_dependency "debug", ">= 1.0.0"
34
+ spec.add_development_dependency "gem-release", "~> 2.2"
35
+ spec.add_development_dependency "minitest", "~> 5.0"
36
+ spec.add_development_dependency "minitest-spec-context", "~> 0.0.4"
37
+ spec.add_development_dependency "rake", "~> 13.0"
38
+ spec.add_development_dependency "rubocop", "~> 1.21"
39
+ spec.add_development_dependency "rubocop-minitest", "~> 0.22"
40
+ spec.add_development_dependency "rubocop-rake", "~> 0.6"
41
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strict
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Thompson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-01 00:00:00.000000000 Z
11
+ date: 2022-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: debug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: gem-release
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '5.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest-spec-context
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.0.4
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.0.4
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rake
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +108,34 @@ dependencies:
80
108
  - - "~>"
81
109
  - !ruby/object:Gem::Version
82
110
  version: '1.21'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-minitest
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.22'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.22'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rake
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.6'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.6'
83
139
  description:
84
140
  email:
85
141
  - me@kkt.dev
@@ -96,9 +152,48 @@ files:
96
152
  - README.md
97
153
  - Rakefile
98
154
  - lib/strict.rb
155
+ - lib/strict/accessor/attributes.rb
156
+ - lib/strict/accessor/module.rb
157
+ - lib/strict/assignment_error.rb
158
+ - lib/strict/attribute.rb
159
+ - lib/strict/attributes/class.rb
160
+ - lib/strict/attributes/coercer.rb
161
+ - lib/strict/attributes/configuration.rb
162
+ - lib/strict/attributes/dsl.rb
163
+ - lib/strict/attributes/instance.rb
164
+ - lib/strict/coercers/array.rb
165
+ - lib/strict/coercers/hash.rb
166
+ - lib/strict/dsl/coercible.rb
167
+ - lib/strict/dsl/validatable.rb
99
168
  - lib/strict/error.rb
169
+ - lib/strict/implementation_does_not_conform_error.rb
170
+ - lib/strict/initialization_error.rb
171
+ - lib/strict/interface.rb
172
+ - lib/strict/interfaces/instance.rb
173
+ - lib/strict/method.rb
174
+ - lib/strict/method_call_error.rb
175
+ - lib/strict/method_definition_error.rb
176
+ - lib/strict/method_return_error.rb
177
+ - lib/strict/methods/configuration.rb
178
+ - lib/strict/methods/dsl.rb
179
+ - lib/strict/methods/module.rb
180
+ - lib/strict/methods/verifiable_method.rb
181
+ - lib/strict/object.rb
182
+ - lib/strict/parameter.rb
183
+ - lib/strict/reader/attributes.rb
184
+ - lib/strict/reader/module.rb
185
+ - lib/strict/return.rb
186
+ - lib/strict/validators/all_of.rb
187
+ - lib/strict/validators/any_of.rb
188
+ - lib/strict/validators/anything.rb
189
+ - lib/strict/validators/array_of.rb
190
+ - lib/strict/validators/boolean.rb
191
+ - lib/strict/validators/hash_of.rb
192
+ - lib/strict/validators/range_of.rb
193
+ - lib/strict/value.rb
100
194
  - lib/strict/version.rb
101
195
  - sig/strict.rbs
196
+ - strict.gemspec
102
197
  homepage: https://github.com/kylekthompson/strict
103
198
  licenses:
104
199
  - MIT