kind 3.1.0 → 4.0.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +1 -0
  3. data/.travis.sh +37 -12
  4. data/.travis.yml +6 -3
  5. data/CHANGELOG.md +1230 -0
  6. data/Gemfile +10 -2
  7. data/README.md +817 -487
  8. data/lib/kind.rb +53 -283
  9. data/lib/kind/active_model/kind_validator.rb +7 -7
  10. data/lib/kind/core.rb +9 -0
  11. data/lib/kind/core/deprecation.rb +29 -0
  12. data/lib/kind/core/kind.rb +61 -0
  13. data/lib/kind/core/undefined.rb +7 -0
  14. data/lib/kind/deprecations/built_in_type_checkers.rb +23 -0
  15. data/lib/kind/{checker.rb → deprecations/checker.rb} +3 -2
  16. data/lib/kind/{checker → deprecations/checker}/factory.rb +1 -5
  17. data/lib/kind/{checker → deprecations/checker}/protocol.rb +3 -3
  18. data/lib/kind/deprecations/is.rb +35 -0
  19. data/lib/kind/deprecations/of.rb +258 -0
  20. data/lib/kind/{types.rb → deprecations/types.rb} +14 -8
  21. data/lib/kind/dig.rb +13 -9
  22. data/lib/kind/empty.rb +5 -11
  23. data/lib/kind/error.rb +2 -6
  24. data/lib/kind/maybe.rb +12 -161
  25. data/lib/kind/maybe/none.rb +57 -0
  26. data/lib/kind/maybe/result.rb +51 -0
  27. data/lib/kind/maybe/some.rb +90 -0
  28. data/lib/kind/maybe/typed.rb +29 -0
  29. data/lib/kind/maybe/wrappable.rb +35 -0
  30. data/lib/kind/presence.rb +33 -0
  31. data/lib/kind/try.rb +36 -0
  32. data/lib/kind/type_checker.rb +73 -0
  33. data/lib/kind/type_checkers.rb +30 -0
  34. data/lib/kind/type_checkers/core/array.rb +17 -0
  35. data/lib/kind/type_checkers/core/class.rb +13 -0
  36. data/lib/kind/type_checkers/core/comparable.rb +13 -0
  37. data/lib/kind/type_checkers/core/enumerable.rb +13 -0
  38. data/lib/kind/type_checkers/core/enumerator.rb +13 -0
  39. data/lib/kind/type_checkers/core/file.rb +13 -0
  40. data/lib/kind/type_checkers/core/float.rb +13 -0
  41. data/lib/kind/type_checkers/core/hash.rb +17 -0
  42. data/lib/kind/type_checkers/core/integer.rb +13 -0
  43. data/lib/kind/type_checkers/core/io.rb +13 -0
  44. data/lib/kind/type_checkers/core/method.rb +13 -0
  45. data/lib/kind/type_checkers/core/module.rb +17 -0
  46. data/lib/kind/type_checkers/core/numeric.rb +13 -0
  47. data/lib/kind/type_checkers/core/proc.rb +13 -0
  48. data/lib/kind/type_checkers/core/queue.rb +14 -0
  49. data/lib/kind/type_checkers/core/range.rb +13 -0
  50. data/lib/kind/type_checkers/core/regexp.rb +13 -0
  51. data/lib/kind/type_checkers/core/string.rb +17 -0
  52. data/lib/kind/type_checkers/core/struct.rb +13 -0
  53. data/lib/kind/type_checkers/core/symbol.rb +13 -0
  54. data/lib/kind/type_checkers/core/time.rb +13 -0
  55. data/lib/kind/type_checkers/custom/boolean.rb +19 -0
  56. data/lib/kind/type_checkers/custom/callable.rb +19 -0
  57. data/lib/kind/type_checkers/custom/lambda.rb +19 -0
  58. data/lib/kind/type_checkers/stdlib/open_struct.rb +13 -0
  59. data/lib/kind/type_checkers/stdlib/set.rb +17 -0
  60. data/lib/kind/undefined.rb +4 -2
  61. data/lib/kind/validator.rb +1 -1
  62. data/lib/kind/version.rb +1 -1
  63. data/test.sh +4 -4
  64. metadata +51 -9
  65. data/lib/kind/is.rb +0 -19
  66. data/lib/kind/of.rb +0 -11
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module KIND
5
+ def self.null?(value) # :nodoc:
6
+ value.nil? || Undefined == value
7
+ end
8
+
9
+ def self.of?(kind, values) # :nodoc:
10
+ of_kind = -> value { kind === value }
11
+
12
+ values.empty? ? of_kind : values.all?(&of_kind)
13
+ end
14
+
15
+ def self.of!(kind, value, kind_name = nil) # :nodoc:
16
+ return value if kind === value
17
+
18
+ error!(kind_name || kind.name, value)
19
+ end
20
+
21
+ def self.error!(kind_name, value) # :nodoc:
22
+ raise Error.new(kind_name, value)
23
+ end
24
+
25
+ def self.of_class?(value) # :nodoc:
26
+ value.kind_of?(::Class)
27
+ end
28
+
29
+ def self.of_module?(value) # :nodoc:
30
+ ::Module == value || (value.is_a?(::Module) && !of_class?(value))
31
+ end
32
+
33
+ def self.of_module_or_class!(value) # :nodoc:
34
+ of!(::Module, value, 'Module/Class')
35
+ end
36
+
37
+ def self.respond_to!(method_name, value) # :nodoc:
38
+ return value if value.respond_to?(method_name)
39
+
40
+ raise Error.new("expected #{value} to respond to :#{method_name}")
41
+ end
42
+
43
+ def self.is?(expected, value) # :nodoc:
44
+ is!(of_module_or_class!(expected), value)
45
+ end
46
+
47
+ def self.is!(expected_kind, value) # :nodoc:
48
+ kind = of_module_or_class!(value)
49
+
50
+ if of_class?(kind)
51
+ kind <= expected_kind || expected_kind == ::Class
52
+ else
53
+ kind == expected_kind || kind.kind_of?(expected_kind)
54
+ end
55
+ end
56
+
57
+ def self.value(kind, arg, default) # :nodoc:
58
+ kind === arg ? arg : default
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ UNDEFINED = Object.new.freeze
5
+
6
+ private_constant :UNDEFINED
7
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ # -- Classes
5
+ [
6
+ ::String, ::Symbol, ::Numeric, ::Integer, ::Float, ::Regexp, ::Time,
7
+ ::Array, ::Range, ::Hash, ::Struct, ::Enumerator, ::Set, ::OpenStruct,
8
+ ::Method, ::Proc,
9
+ ::IO, ::File
10
+ ].each { |klass| Types.add(klass) }
11
+
12
+ Types.add(::Queue, name: 'Queue'.freeze)
13
+
14
+ # -- Modules
15
+ [
16
+ ::Enumerable, ::Comparable
17
+ ].each { |klass| Types.add(klass) }
18
+
19
+ # -- Kind::Of::Maybe
20
+
21
+ Types.add(Kind::Maybe::Result, name: 'Maybe'.freeze)
22
+ Types.add(Kind::Maybe::Result, name: 'Optional'.freeze)
23
+ end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'kind/checker/factory'
4
- require 'kind/checker/protocol'
3
+ require 'kind/deprecations/checker/factory'
4
+ require 'kind/deprecations/checker/protocol'
5
+
5
6
  module Kind
6
7
  class Checker
7
8
  include Protocol
@@ -15,10 +15,6 @@ module Kind
15
15
  @__checkers__ = {}
16
16
  end
17
17
 
18
- MODULE_OR_CLASS = 'Module/Class'.freeze
19
-
20
- private_constant :MODULE_OR_CLASS
21
-
22
18
  def create(kind)
23
19
  @__checkers__[kind] ||= begin
24
20
  kind_name = kind.name
@@ -26,7 +22,7 @@ module Kind
26
22
  if Kind::Of.const_defined?(kind_name, false)
27
23
  Kind::Of.const_get(kind_name)
28
24
  else
29
- Kind::Checker.new(Kind::Of.(Module, kind, MODULE_OR_CLASS))
25
+ Kind::Checker.new(Kind.of_module_or_class(kind))
30
26
  end
31
27
  end
32
28
  end
@@ -4,15 +4,15 @@ module Kind
4
4
  class Checker
5
5
  module Protocol
6
6
  def class?(value)
7
- Kind::Is.__call__(__kind, value)
7
+ KIND.is?(__kind, value)
8
8
  end
9
9
 
10
10
  def instance(value, options = Empty::HASH)
11
11
  default = options[:or]
12
12
 
13
- return Kind::Of.(__kind, value) if ::Kind::Maybe::Value.none?(default)
13
+ return KIND.of!(__kind, value) if ::Kind::KIND.null?(default)
14
14
 
15
- Kind::Undefined != value && instance?(value) ? value : Kind::Of.(__kind, default)
15
+ Kind::Undefined != value && instance?(value) ? value : KIND.of!(__kind, default)
16
16
  end
17
17
 
18
18
  def [](value, options = options = Empty::HASH)
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module Is
5
+ def self.call(expected, object)
6
+ DEPRECATION.warn_method_replacement('Kind::Is.call', 'Kind::KIND.is?')
7
+
8
+ KIND.is?(expected, object)
9
+ end
10
+
11
+ def self.Class(value)
12
+ DEPRECATION.warn_method_replacement('Kind::Is.Class', 'Kind.of_class?')
13
+
14
+ Kind.of_class?(value)
15
+ end
16
+
17
+ def self.Module(value)
18
+ DEPRECATION.warn_method_replacement('Kind::Is.Module', 'Kind.of_module?')
19
+
20
+ Kind.of_module?(value)
21
+ end
22
+
23
+ def self.Boolean(value)
24
+ DEPRECATION.warn_removal('Kind::Is.Boolean')
25
+
26
+ Kind::Class[value] <= TrueClass || value <= FalseClass
27
+ end
28
+
29
+ def self.Callable(value)
30
+ DEPRECATION.warn_method_replacement('Kind::Is.Callable', 'Kind::Callable?')
31
+
32
+ value.respond_to?(:call)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,258 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module Of
5
+ def self.call(kind, object, kind_name = nil)
6
+ DEPRECATION.warn_method_replacement('Kind::Of.call', 'Kind::KIND.of!')
7
+
8
+ KIND.of!(kind, object, kind_name)
9
+ end
10
+
11
+ # -- Class
12
+
13
+ def self.Class(object = Undefined)
14
+ DEPRECATION.warn_method_replacement('Kind::Of::Class', 'Kind::Class')
15
+
16
+ return Class if Undefined == object
17
+
18
+ self.call(::Class, object)
19
+ end
20
+
21
+ const_set(:Class, ::Module.new do
22
+ extend Checker::Protocol
23
+
24
+ def self.__kind; ::Class; end
25
+
26
+ def self.class?(value); Kind.of_class?(value); end
27
+
28
+ def self.__is_instance__(value); class?(value); end
29
+ end)
30
+
31
+ def self.Class?(*args)
32
+ DEPRECATION.warn_method_replacement('Kind::Of::Class?', 'Kind::Class?')
33
+
34
+ Kind::Class?(*args)
35
+ end
36
+
37
+ # -- Module
38
+
39
+ def self.Module(object = Undefined)
40
+ DEPRECATION.warn_method_replacement('Kind::Of::Module', 'Kind::Module')
41
+
42
+ return Module if Undefined == object
43
+
44
+ self.call(::Module, object)
45
+ end
46
+
47
+ const_set(:Module, ::Module.new do
48
+ extend Checker::Protocol
49
+
50
+ def self.__kind_undefined(value)
51
+ __kind_error(Kind::Undefined) if Kind::Undefined == value
52
+
53
+ yield
54
+ end
55
+
56
+ def self.__kind_error(value)
57
+ raise Kind::Error.new('Module'.freeze, value)
58
+ end
59
+
60
+ def self.__kind_of(value)
61
+ return value if Kind.of_module?(value)
62
+
63
+ __kind_error(value)
64
+ end
65
+
66
+ def self.__kind; ::Module; end
67
+
68
+ def self.class?(value); Kind.of_module?(value); end
69
+
70
+ def self.instance(value, options = Empty::HASH)
71
+ default = options[:or]
72
+
73
+ if ::Kind::KIND.null?(default)
74
+ __kind_undefined(value) { __kind_of(value) }
75
+ else
76
+ return value if Kind::Undefined != value && instance?(value)
77
+
78
+ __kind_undefined(default) { __kind_of(default) }
79
+ end
80
+ end
81
+
82
+ def self.__is_instance__(value); class?(value); end
83
+ end)
84
+
85
+ def self.Module?(*args)
86
+ DEPRECATION.warn_method_replacement('Kind::Of::Module?', 'Kind::Module?')
87
+
88
+ Kind::Module?(*args)
89
+ end
90
+
91
+ # -- Boolean
92
+
93
+ def self.Boolean(object = Undefined, options = Empty::HASH)
94
+ DEPRECATION.warn_method_replacement('Kind::Of::Boolean', 'Kind::Boolean')
95
+
96
+ default = options[:or]
97
+
98
+ return Kind::Of::Boolean if Undefined == object && default.nil?
99
+
100
+ bool = object.nil? ? default : object
101
+
102
+ return bool if bool.is_a?(::TrueClass) || bool.is_a?(::FalseClass)
103
+
104
+ raise Kind::Error.new('Boolean'.freeze, bool)
105
+ end
106
+
107
+ const_set(:Boolean, ::Module.new do
108
+ extend Checker::Protocol
109
+
110
+ def self.__kind; [TrueClass, FalseClass].freeze; end
111
+
112
+ def self.class?(value); Kind.is.Boolean(value); end
113
+
114
+ def self.instance(value, options= Empty::HASH)
115
+ default = options[:or]
116
+
117
+ if ::Kind::KIND.null?(default)
118
+ __kind_undefined(value) { Kind::Of::Boolean(value) }
119
+ else
120
+ return value if Kind::Undefined != value && instance?(value)
121
+
122
+ __kind_undefined(default) { Kind::Of::Boolean(default) }
123
+ end
124
+ end
125
+
126
+ def self.__kind_undefined(value)
127
+ if Kind::Undefined == value
128
+ raise Kind::Error.new('Boolean'.freeze, Kind::Undefined)
129
+ else
130
+ yield
131
+ end
132
+ end
133
+
134
+ def self.__is_instance__(value);
135
+ value.is_a?(TrueClass) || value.is_a?(FalseClass)
136
+ end
137
+
138
+ def self.or_undefined(value)
139
+ result = or_nil(value)
140
+ result.nil? ? Kind::Undefined : result
141
+ end
142
+ end)
143
+
144
+ def self.Boolean?(*args)
145
+ DEPRECATION.warn_method_replacement('Kind::Of::Boolean?', 'Kind::Boolean?')
146
+
147
+ Kind::Boolean?(*args)
148
+ end
149
+
150
+ # -- Lambda
151
+
152
+ def self.Lambda(object = Undefined, options = Empty::HASH)
153
+ DEPRECATION.warn_method_replacement('Kind::Of::Lambda', 'Kind::Lambda')
154
+
155
+ default = options[:or]
156
+
157
+ return Kind::Of::Lambda if Undefined == object && default.nil?
158
+
159
+ func = object || default
160
+
161
+ return func if func.is_a?(::Proc) && func.lambda?
162
+
163
+ raise Kind::Error.new('Lambda'.freeze, func)
164
+ end
165
+
166
+ const_set(:Lambda, ::Module.new do
167
+ extend Checker::Protocol
168
+
169
+ def self.__kind; ::Proc; end
170
+
171
+ def self.instance(value, options = Empty::HASH)
172
+ default = options[:or]
173
+
174
+ if ::Kind::KIND.null?(default)
175
+ __kind_undefined(value) { Kind::Of::Lambda(value) }
176
+ else
177
+ return value if Kind::Undefined != value && instance?(value)
178
+
179
+ __kind_undefined(default) { Kind::Of::Lambda(default) }
180
+ end
181
+ end
182
+
183
+ def self.__kind_undefined(value)
184
+ if Kind::Undefined == value
185
+ raise Kind::Error.new('Lambda'.freeze, Kind::Undefined)
186
+ else
187
+ yield
188
+ end
189
+ end
190
+
191
+ def self.__is_instance__(value)
192
+ value.is_a?(__kind) && value.lambda?
193
+ end
194
+ end)
195
+
196
+ def self.Lambda?(*args)
197
+ DEPRECATION.warn_method_replacement('Kind::Of::Lambda?', 'Kind::Lambda?')
198
+
199
+ Kind::Lambda?(*args)
200
+ end
201
+
202
+ # -- Callable
203
+
204
+ def self.Callable(object = Undefined, options = Empty::HASH)
205
+ DEPRECATION.warn_method_replacement('Kind::Of::Callable', 'Kind::Callable')
206
+
207
+ default = options[:or]
208
+
209
+ return Kind::Of::Callable if Undefined == object && default.nil?
210
+
211
+ callable = object || default
212
+
213
+ return callable if callable.respond_to?(:call)
214
+
215
+ raise Kind::Error.new('Callable'.freeze, callable)
216
+ end
217
+
218
+ const_set(:Callable, ::Module.new do
219
+ extend Checker::Protocol
220
+
221
+ def self.__kind; Object; end
222
+
223
+ def self.class?(value)
224
+ Kind::Is::Callable(value)
225
+ end
226
+
227
+ def self.instance(value, options = Empty::HASH)
228
+ default = options[:or]
229
+
230
+ if ::Kind::KIND.null?(default)
231
+ __kind_undefined(value) { Kind::Of::Callable(value) }
232
+ else
233
+ return value if Kind::Undefined != value && instance?(value)
234
+
235
+ __kind_undefined(default) { Kind::Of::Callable(default) }
236
+ end
237
+ end
238
+
239
+ def self.__kind_undefined(value)
240
+ if Kind::Undefined == value
241
+ raise Kind::Error.new('Callable'.freeze, Kind::Undefined)
242
+ else
243
+ yield
244
+ end
245
+ end
246
+
247
+ def self.__is_instance__(value);
248
+ value.respond_to?(:call)
249
+ end
250
+ end)
251
+
252
+ def self.Callable?(*args)
253
+ DEPRECATION.warn_method_replacement('Kind::Of::Callable?', 'Kind::Callable?')
254
+
255
+ Kind::Callable?(*args)
256
+ end
257
+ end
258
+ end
@@ -8,6 +8,8 @@ module Kind
8
8
 
9
9
  KIND_OF = <<-RUBY
10
10
  def self.%{method_name}(object = Undefined, options = Empty::HASH)
11
+ DEPRECATION.warn_method_replacement('Kind::Of::%{method_name}', 'Kind::%{method_name}')
12
+
11
13
  default = options[:or]
12
14
 
13
15
  return Kind::Of::%{kind_name} if Undefined == object && default.nil?
@@ -16,29 +18,33 @@ module Kind
16
18
 
17
19
  return object if is_instance
18
20
 
19
- Kind::Of.(::%{kind_name_to_check}, object && default ? default : object || default)
21
+ KIND.of!(::%{kind_name_to_check}, object && default ? default : object || default)
20
22
  end
21
23
  RUBY
22
24
 
23
25
  KIND_OF_IS = <<-RUBY
24
26
  def self.%{method_name}?(*args)
27
+ DEPRECATION.warn_method_replacement('Kind::Of::%{method_name}?', 'Kind::%{method_name}?')
28
+
25
29
  Kind::Of::%{kind_name}.instance?(*args)
26
30
  end
27
31
  RUBY
28
32
 
29
33
  KIND_IS = <<-RUBY
30
- def self.%{method_name}(value = Undefined)
31
- return Kind::Is::%{kind_name} if Undefined == value
34
+ def self.%{method_name}(value)
35
+ DEPRECATION.warn_removal('Kind::Is::%{method_name}')
32
36
 
33
- Kind::Is.__call__(::%{kind_name_to_check}, value)
37
+ KIND.is!(::%{kind_name_to_check}, value)
34
38
  end
35
39
  RUBY
36
40
 
37
41
  private_constant :KIND_OF, :KIND_IS, :COLONS
38
42
 
39
43
  def add(kind, name: nil)
40
- kind_name = Kind.of.Module(kind).name
41
- checker = name ? Kind::Of.(String, name) : kind_name
44
+ DEPRECATION.warn_removal('Kind::Types')
45
+
46
+ kind_name = KIND.of_module_or_class!(kind).name
47
+ checker = name ? Kind::String[name] : kind_name
42
48
 
43
49
  if checker.include?(COLONS)
44
50
  add_kind_with_namespace(checker, method_name: name)
@@ -99,7 +105,7 @@ module Kind
99
105
  params[:kind_name_to_check] ||= kind_name
100
106
 
101
107
  kind_checker = ::Module.new { extend Checker::Protocol }
102
- kind_checker.module_eval("def self.__kind; #{params[:kind_name_to_check]}; end")
108
+ kind_checker.module_eval("def self.__kind; ::#{params[:kind_name_to_check]}; end")
103
109
 
104
110
  kind_of_mod.instance_eval(KIND_OF % params)
105
111
  kind_of_mod.const_set(method_name, kind_checker)
@@ -108,7 +114,7 @@ module Kind
108
114
 
109
115
  unless kind_is_mod.respond_to?(method_name)
110
116
  kind_is_mod.instance_eval(KIND_IS % params)
111
- kind_is_mod.const_set(method_name, Module.new) if create_kind_is_mod
117
+ kind_is_mod.const_set(method_name, ::Module.new) if create_kind_is_mod
112
118
  end
113
119
  end
114
120
  end