dry-types 1.5.1 → 1.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -0
- data/LICENSE +1 -1
- data/README.md +7 -13
- data/dry-types.gemspec +19 -18
- data/lib/dry/types/array/constructor.rb +0 -2
- data/lib/dry/types/array/member.rb +1 -3
- data/lib/dry/types/array.rb +0 -3
- data/lib/dry/types/builder.rb +43 -14
- data/lib/dry/types/builder_methods.rb +1 -1
- data/lib/dry/types/coercions/params.rb +4 -3
- data/lib/dry/types/compat.rb +1 -0
- data/lib/dry/types/compiler.rb +1 -3
- data/lib/dry/types/composition.rb +152 -0
- data/lib/dry/types/constrained.rb +0 -5
- data/lib/dry/types/constraints.rb +3 -7
- data/lib/dry/types/constructor/function.rb +8 -9
- data/lib/dry/types/constructor.rb +4 -10
- data/lib/dry/types/container.rb +1 -3
- data/lib/dry/types/core.rb +2 -3
- data/lib/dry/types/decorator.rb +0 -2
- data/lib/dry/types/default.rb +3 -6
- data/lib/dry/types/enum.rb +0 -3
- data/lib/dry/types/errors.rb +13 -1
- data/lib/dry/types/extensions/maybe.rb +8 -5
- data/lib/dry/types/extensions/monads.rb +7 -2
- data/lib/dry/types/fn_container.rb +0 -2
- data/lib/dry/types/hash/constructor.rb +2 -4
- data/lib/dry/types/hash.rb +1 -6
- data/lib/dry/types/implication.rb +66 -0
- data/lib/dry/types/intersection.rb +108 -0
- data/lib/dry/types/lax.rb +1 -4
- data/lib/dry/types/map.rb +9 -3
- data/lib/dry/types/module.rb +18 -9
- data/lib/dry/types/nominal.rb +2 -13
- data/lib/dry/types/predicate_inferrer.rb +8 -9
- data/lib/dry/types/predicate_registry.rb +7 -7
- data/lib/dry/types/primitive_inferrer.rb +0 -2
- data/lib/dry/types/printer/composition.rb +44 -0
- data/lib/dry/types/printer.rb +116 -131
- data/lib/dry/types/result.rb +0 -2
- data/lib/dry/types/schema/key.rb +1 -4
- data/lib/dry/types/schema.rb +6 -4
- data/lib/dry/types/sum.rb +3 -95
- data/lib/dry/types/type.rb +1 -3
- data/lib/dry/types/version.rb +1 -1
- data/lib/dry/types.rb +49 -22
- metadata +32 -46
data/lib/dry/types/decorator.rb
CHANGED
data/lib/dry/types/default.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/core/equalizer"
|
4
|
-
require "dry/types/decorator"
|
5
|
-
|
6
3
|
module Dry
|
7
4
|
module Types
|
8
5
|
# Default types are useful when a missing value should be replaced by a default one
|
@@ -53,7 +50,7 @@ module Dry
|
|
53
50
|
# @param [Object] value
|
54
51
|
#
|
55
52
|
# @api private
|
56
|
-
def initialize(type, value, **
|
53
|
+
def initialize(type, value, **)
|
57
54
|
super
|
58
55
|
@value = value
|
59
56
|
end
|
@@ -65,8 +62,8 @@ module Dry
|
|
65
62
|
# @return [Default]
|
66
63
|
#
|
67
64
|
# @api public
|
68
|
-
def constrained(
|
69
|
-
type.constrained(
|
65
|
+
def constrained(...)
|
66
|
+
type.constrained(...).default(value)
|
70
67
|
end
|
71
68
|
|
72
69
|
# @return [true]
|
data/lib/dry/types/enum.rb
CHANGED
data/lib/dry/types/errors.rb
CHANGED
@@ -51,6 +51,7 @@ module Dry
|
|
51
51
|
|
52
52
|
# @param [Array<CoercionError>] errors
|
53
53
|
def initialize(errors)
|
54
|
+
super("")
|
54
55
|
@errors = errors
|
55
56
|
end
|
56
57
|
|
@@ -66,11 +67,22 @@ module Dry
|
|
66
67
|
end
|
67
68
|
|
68
69
|
class SchemaError < CoercionError
|
70
|
+
# @return [String, Symbol]
|
71
|
+
attr_reader :key
|
72
|
+
|
73
|
+
# @return [Object]
|
74
|
+
attr_reader :value
|
75
|
+
|
69
76
|
# @param [String,Symbol] key
|
70
77
|
# @param [Object] value
|
71
78
|
# @param [String, #to_s] result
|
72
79
|
def initialize(key, value, result)
|
73
|
-
|
80
|
+
@key = key
|
81
|
+
@value = value
|
82
|
+
super(
|
83
|
+
"#{value.inspect} (#{value.class}) has invalid type "\
|
84
|
+
"for :#{key} violates constraints (#{result} failed)"
|
85
|
+
)
|
74
86
|
end
|
75
87
|
end
|
76
88
|
|
@@ -1,8 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/
|
4
|
-
require "dry/monads/
|
5
|
-
|
3
|
+
require "dry/monads"
|
4
|
+
require "dry/monads/version"
|
5
|
+
|
6
|
+
if Gem::Version.new(Dry::Monads::VERSION) < Gem::Version.new("1.5.0")
|
7
|
+
raise "dry-types requires dry-monads >= 1.5.0"
|
8
|
+
end
|
6
9
|
|
7
10
|
module Dry
|
8
11
|
module Types
|
@@ -15,7 +18,7 @@ module Dry
|
|
15
18
|
include Decorator
|
16
19
|
include Builder
|
17
20
|
include Printable
|
18
|
-
include ::Dry::Monads
|
21
|
+
include ::Dry::Monads[:maybe]
|
19
22
|
|
20
23
|
# @param [Dry::Monads::Maybe, Object] input
|
21
24
|
#
|
@@ -99,7 +102,7 @@ module Dry
|
|
99
102
|
end
|
100
103
|
|
101
104
|
# @api private
|
102
|
-
class Schema::Key
|
105
|
+
class Schema::Key # rubocop:disable Style/ClassAndModuleChildren
|
103
106
|
# @api private
|
104
107
|
def maybe
|
105
108
|
__new__(type.maybe)
|
@@ -1,6 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/monads
|
3
|
+
require "dry/monads"
|
4
|
+
require "dry/monads/version"
|
5
|
+
|
6
|
+
if Gem::Version.new(Dry::Monads::VERSION) < Gem::Version.new("1.5.0")
|
7
|
+
raise "dry-types requires dry-monads >= 1.5.0"
|
8
|
+
end
|
4
9
|
|
5
10
|
module Dry
|
6
11
|
module Types
|
@@ -8,7 +13,7 @@ module Dry
|
|
8
13
|
#
|
9
14
|
# @api public
|
10
15
|
class Result
|
11
|
-
include Dry::Monads
|
16
|
+
include ::Dry::Monads[:result]
|
12
17
|
|
13
18
|
# Turn result into a monad
|
14
19
|
#
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/types/constructor"
|
4
|
-
|
5
3
|
module Dry
|
6
4
|
module Types
|
7
5
|
# Hash type exposes additional APIs for working with schema hashes
|
@@ -24,8 +22,8 @@ module Dry
|
|
24
22
|
# @see Dry::Types::Array#of
|
25
23
|
#
|
26
24
|
# @api public
|
27
|
-
def schema(
|
28
|
-
type.schema(
|
25
|
+
def schema(...)
|
26
|
+
type.schema(...).constructor(fn, meta: meta)
|
29
27
|
end
|
30
28
|
end
|
31
29
|
end
|
data/lib/dry/types/hash.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/types/hash/constructor"
|
4
|
-
|
5
3
|
module Dry
|
6
4
|
module Types
|
7
5
|
# Hash types can be used to define maps and schemas
|
@@ -51,7 +49,7 @@ module Dry
|
|
51
49
|
# @api private
|
52
50
|
def weak(*)
|
53
51
|
raise "Support for old hash schemas was removed, please refer to the CHANGELOG "\
|
54
|
-
"on how to proceed with the new API https://github.com/dry-rb/dry-types/blob/
|
52
|
+
"on how to proceed with the new API https://github.com/dry-rb/dry-types/blob/main/CHANGELOG.md"
|
55
53
|
end
|
56
54
|
alias_method :permissive, :weak
|
57
55
|
alias_method :strict, :weak
|
@@ -132,6 +130,3 @@ module Dry
|
|
132
130
|
end
|
133
131
|
end
|
134
132
|
end
|
135
|
-
|
136
|
-
require "dry/types/schema/key"
|
137
|
-
require "dry/types/schema"
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Types
|
5
|
+
# Implication type
|
6
|
+
#
|
7
|
+
# @api public
|
8
|
+
class Implication
|
9
|
+
include Composition
|
10
|
+
|
11
|
+
def self.operator
|
12
|
+
:>
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param [Object] input
|
16
|
+
#
|
17
|
+
# @return [Object]
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
def call_unsafe(input)
|
21
|
+
if left.try(input).success?
|
22
|
+
right.call_unsafe(input)
|
23
|
+
else
|
24
|
+
input
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param [Object] input
|
29
|
+
#
|
30
|
+
# @return [Object]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
def call_safe(input, &block)
|
34
|
+
if left.try(input).success?
|
35
|
+
right.call_safe(input, &block)
|
36
|
+
else
|
37
|
+
input
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param [Object] input
|
42
|
+
#
|
43
|
+
# @api public
|
44
|
+
def try(input)
|
45
|
+
if left.try(input).success?
|
46
|
+
right.try(input)
|
47
|
+
else
|
48
|
+
Result::Success.new(input)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# @param [Object] value
|
53
|
+
#
|
54
|
+
# @return [Boolean]
|
55
|
+
#
|
56
|
+
# @api private
|
57
|
+
def primitive?(value)
|
58
|
+
if left.primitive?(value)
|
59
|
+
right.primitive?(value)
|
60
|
+
else
|
61
|
+
true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/equalizer"
|
4
|
+
require "dry/types/options"
|
5
|
+
require "dry/types/meta"
|
6
|
+
|
7
|
+
module Dry
|
8
|
+
module Types
|
9
|
+
# Intersection type
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
class Intersection
|
13
|
+
include Composition
|
14
|
+
|
15
|
+
def self.operator
|
16
|
+
:&
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [Object] input
|
20
|
+
#
|
21
|
+
# @return [Object]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
def call_unsafe(input)
|
25
|
+
merge_results(left.call_unsafe(input), right.call_unsafe(input))
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param [Object] input
|
29
|
+
#
|
30
|
+
# @return [Object]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
def call_safe(input, &block)
|
34
|
+
try_sides(input, &block).input
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param [Object] input
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
def try(input)
|
41
|
+
try_sides(input) do |failure|
|
42
|
+
if block_given?
|
43
|
+
yield(failure)
|
44
|
+
else
|
45
|
+
failure
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param [Object] value
|
51
|
+
#
|
52
|
+
# @return [Boolean]
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
def primitive?(value)
|
56
|
+
left.primitive?(value) && right.primitive?(value)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# @api private
|
62
|
+
def try_sides(input, &block)
|
63
|
+
results = []
|
64
|
+
|
65
|
+
[left, right].each do |side|
|
66
|
+
result = try_side(side, input, &block)
|
67
|
+
return result if result.failure?
|
68
|
+
|
69
|
+
results << result
|
70
|
+
end
|
71
|
+
|
72
|
+
Result::Success.new(merge_results(*results.map(&:input)))
|
73
|
+
end
|
74
|
+
|
75
|
+
# @api private
|
76
|
+
def try_side(side, input)
|
77
|
+
failure = nil
|
78
|
+
|
79
|
+
result = side.try(input) do |f|
|
80
|
+
failure = f
|
81
|
+
yield(f)
|
82
|
+
end
|
83
|
+
|
84
|
+
if result.is_a?(Result)
|
85
|
+
result
|
86
|
+
elsif failure
|
87
|
+
Result::Failure.new(result, failure)
|
88
|
+
else
|
89
|
+
Result::Success.new(result)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @api private
|
94
|
+
def merge_results(left_result, right_result)
|
95
|
+
case left_result
|
96
|
+
when ::Array
|
97
|
+
left_result
|
98
|
+
.zip(right_result)
|
99
|
+
.map { |lhs, rhs| merge_results(lhs, rhs) }
|
100
|
+
when ::Hash
|
101
|
+
left_result.merge(right_result)
|
102
|
+
else
|
103
|
+
left_result
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/lib/dry/types/lax.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/core/deprecations"
|
4
|
-
require "dry/types/decorator"
|
5
|
-
|
6
3
|
module Dry
|
7
4
|
module Types
|
8
5
|
# Lax types rescue from type-related errors when constructors fail
|
@@ -68,7 +65,7 @@ module Dry
|
|
68
65
|
end
|
69
66
|
end
|
70
67
|
|
71
|
-
extend ::Dry::Core::Deprecations[:
|
68
|
+
extend ::Dry::Core::Deprecations[:"dry-types"]
|
72
69
|
Safe = Lax
|
73
70
|
deprecate_constant(:Safe)
|
74
71
|
end
|
data/lib/dry/types/map.rb
CHANGED
@@ -14,15 +14,17 @@ module Dry
|
|
14
14
|
# # => {1 => 'right'}
|
15
15
|
#
|
16
16
|
# type.('1' => 'wrong')
|
17
|
-
# # Dry::Types::MapError: "1" violates constraints (type?(Integer, "1")
|
17
|
+
# # Dry::Types::MapError: "1" violates constraints (type?(Integer, "1")
|
18
|
+
# # AND gteq?(1, "1")
|
19
|
+
# # AND lteq?(10, "1") failed)
|
18
20
|
#
|
19
21
|
# type.(11 => 'wrong')
|
20
22
|
# # Dry::Types::MapError: 11 violates constraints (lteq?(10, 11) failed)
|
21
23
|
#
|
22
24
|
# @api public
|
23
25
|
class Map < Nominal
|
24
|
-
def initialize(
|
25
|
-
super(
|
26
|
+
def initialize(primitive, key_type: Types["any"], value_type: Types["any"], meta: EMPTY_HASH)
|
27
|
+
super(primitive, key_type: key_type, value_type: value_type, meta: meta)
|
26
28
|
end
|
27
29
|
|
28
30
|
# @return [Type]
|
@@ -100,6 +102,8 @@ module Dry
|
|
100
102
|
private
|
101
103
|
|
102
104
|
# @api private
|
105
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
106
|
+
# rubocop:disable Metrics/AbcSize
|
103
107
|
def coerce(input)
|
104
108
|
unless primitive?(input)
|
105
109
|
return failure(
|
@@ -131,6 +135,8 @@ module Dry
|
|
131
135
|
failure(input, MultipleError.new(failures))
|
132
136
|
end
|
133
137
|
end
|
138
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
139
|
+
# rubocop:enable Metrics/AbcSize
|
134
140
|
end
|
135
141
|
end
|
136
142
|
end
|
data/lib/dry/types/module.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/core/deprecations"
|
4
3
|
require "dry/types/builder_methods"
|
5
4
|
|
6
5
|
module Dry
|
@@ -8,7 +7,7 @@ module Dry
|
|
8
7
|
# Export types registered in a container as module constants.
|
9
8
|
# @example
|
10
9
|
# module Types
|
11
|
-
# include Dry
|
10
|
+
# include Dry.Types(:strict, :coercible, :nominal, default: :strict)
|
12
11
|
# end
|
13
12
|
#
|
14
13
|
# Types.constants
|
@@ -26,10 +25,10 @@ module Dry
|
|
26
25
|
extend(BuilderMethods)
|
27
26
|
|
28
27
|
if constants.key?(:Nominal)
|
29
|
-
singleton_class.
|
28
|
+
singleton_class.define_method(:included) do |base|
|
30
29
|
super(base)
|
31
30
|
base.instance_exec(const_get(:Nominal, false)) do |nominal|
|
32
|
-
extend Dry::Core::Deprecations[:
|
31
|
+
extend Dry::Core::Deprecations[:"dry-types"]
|
33
32
|
const_set(:Definition, nominal)
|
34
33
|
deprecate_constant(:Definition, message: "Nominal")
|
35
34
|
end
|
@@ -38,13 +37,16 @@ module Dry
|
|
38
37
|
end
|
39
38
|
|
40
39
|
# @api private
|
40
|
+
# rubocop:disable Metrics/AbcSize
|
41
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
42
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
41
43
|
def type_constants(*namespaces, default: Undefined, **aliases)
|
42
44
|
if namespaces.empty? && aliases.empty? && Undefined.equal?(default)
|
43
45
|
default_ns = :Strict
|
44
46
|
elsif Undefined.equal?(default)
|
45
47
|
default_ns = Undefined
|
46
48
|
else
|
47
|
-
default_ns = Inflector.camelize(default).to_sym
|
49
|
+
default_ns = Types::Inflector.camelize(default).to_sym
|
48
50
|
end
|
49
51
|
|
50
52
|
tree = registry_tree
|
@@ -52,7 +54,9 @@ module Dry
|
|
52
54
|
if namespaces.empty? && aliases.empty?
|
53
55
|
modules = tree.select { |_, v| v.is_a?(::Hash) }.map(&:first)
|
54
56
|
else
|
55
|
-
modules = (namespaces + aliases.keys).map { |n|
|
57
|
+
modules = (namespaces + aliases.keys).map { |n|
|
58
|
+
Types::Inflector.camelize(n).to_sym
|
59
|
+
}
|
56
60
|
end
|
57
61
|
|
58
62
|
tree.each_with_object({}) do |(key, value), constants|
|
@@ -64,13 +68,16 @@ module Dry
|
|
64
68
|
constants.update(value) if key == default_ns
|
65
69
|
end
|
66
70
|
end
|
71
|
+
# rubocop:enable Metrics/AbcSize
|
72
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
73
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
67
74
|
|
68
75
|
# @api private
|
69
76
|
def registry_tree
|
70
77
|
@registry_tree ||= @registry.keys.each_with_object({}) { |key, tree|
|
71
78
|
type = @registry[key]
|
72
79
|
*modules, const_name = key.split(".").map { |part|
|
73
|
-
Inflector.camelize(part).to_sym
|
80
|
+
Types::Inflector.camelize(part).to_sym
|
74
81
|
}
|
75
82
|
next if modules.empty?
|
76
83
|
|
@@ -91,9 +98,11 @@ module Dry
|
|
91
98
|
ns.to_sym unless path.empty?
|
92
99
|
}.compact.uniq
|
93
100
|
|
94
|
-
(referenced.uniq - known).
|
101
|
+
unknown = (referenced.uniq - known).first
|
102
|
+
|
103
|
+
if unknown
|
95
104
|
raise ArgumentError,
|
96
|
-
"#{
|
105
|
+
"#{unknown.inspect} is not a known type namespace. "\
|
97
106
|
"Supported options are #{known.map(&:inspect).join(", ")}"
|
98
107
|
end
|
99
108
|
end
|
data/lib/dry/types/nominal.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/core/deprecations"
|
4
|
-
require "dry/core/equalizer"
|
5
|
-
require "dry/types/builder"
|
6
|
-
require "dry/types/result"
|
7
|
-
require "dry/types/options"
|
8
|
-
require "dry/types/meta"
|
9
|
-
|
10
3
|
module Dry
|
11
4
|
module Types
|
12
5
|
# Nominal types define a primitive class and do not apply any constructors or constraints
|
@@ -20,7 +13,7 @@ module Dry
|
|
20
13
|
include Meta
|
21
14
|
include Builder
|
22
15
|
include Printable
|
23
|
-
include Dry::Equalizer(:primitive, :options, :meta, inspect: false, immutable: true)
|
16
|
+
include ::Dry::Equalizer(:primitive, :options, :meta, inspect: false, immutable: true)
|
24
17
|
|
25
18
|
# @return [Class]
|
26
19
|
attr_reader :primitive
|
@@ -199,12 +192,8 @@ module Dry
|
|
199
192
|
end
|
200
193
|
end
|
201
194
|
|
202
|
-
extend Dry::Core::Deprecations[:
|
195
|
+
extend ::Dry::Core::Deprecations[:"dry-types"]
|
203
196
|
Definition = Nominal
|
204
197
|
deprecate_constant(:Definition, message: "Nominal")
|
205
198
|
end
|
206
199
|
end
|
207
|
-
|
208
|
-
require "dry/types/array"
|
209
|
-
require "dry/types/hash"
|
210
|
-
require "dry/types/map"
|
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/core/cache"
|
4
|
-
require "dry/core/class_attributes"
|
5
|
-
require "dry/types/predicate_registry"
|
6
|
-
|
7
3
|
module Dry
|
8
4
|
module Types
|
9
5
|
# PredicateInferrer returns the list of predicates used by a type.
|
@@ -55,7 +51,7 @@ module Dry
|
|
55
51
|
end
|
56
52
|
|
57
53
|
# @api private
|
58
|
-
def infer_predicate(type)
|
54
|
+
def infer_predicate(type) # rubocop:disable Metrics/PerceivedComplexity
|
59
55
|
pred = TYPE_TO_PREDICATE.fetch(type) do
|
60
56
|
if type.name.nil? || self.class.infer_predicate_by_class_name.equal?(false)
|
61
57
|
nil
|
@@ -175,9 +171,9 @@ module Dry
|
|
175
171
|
def visit_predicate(node)
|
176
172
|
pred, args = node
|
177
173
|
|
178
|
-
if pred.equal?(:type?)
|
174
|
+
if pred.equal?(:type?) || !registry.key?(pred)
|
179
175
|
EMPTY_ARRAY
|
180
|
-
|
176
|
+
else
|
181
177
|
*curried, _ = args
|
182
178
|
values = curried.map { |_, v| v }
|
183
179
|
|
@@ -186,11 +182,14 @@ module Dry
|
|
186
182
|
else
|
187
183
|
[pred => values[0]]
|
188
184
|
end
|
189
|
-
else
|
190
|
-
EMPTY_ARRAY
|
191
185
|
end
|
192
186
|
end
|
193
187
|
|
188
|
+
# @api private
|
189
|
+
def visit_map(_node)
|
190
|
+
raise NotImplementedError, "map types are not supported yet"
|
191
|
+
end
|
192
|
+
|
194
193
|
private
|
195
194
|
|
196
195
|
# @api private
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dry/logic/predicates"
|
4
|
-
|
5
3
|
module Dry
|
6
4
|
module Types
|
7
5
|
# A registry with predicate objects from `Dry::Logic::Predicates`
|
@@ -14,20 +12,22 @@ module Dry
|
|
14
12
|
# @api private
|
15
13
|
attr_reader :has_predicate
|
16
14
|
|
15
|
+
KERNEL_RESPOND_TO = ::Kernel.instance_method(:respond_to?)
|
16
|
+
private_constant(:KERNEL_RESPOND_TO)
|
17
|
+
|
17
18
|
# @api private
|
18
19
|
def initialize(predicates = Logic::Predicates)
|
19
20
|
@predicates = predicates
|
20
|
-
@has_predicate = ::Kernel.instance_method(:respond_to?).bind(@predicates)
|
21
21
|
end
|
22
22
|
|
23
23
|
# @api private
|
24
|
-
def
|
25
|
-
predicates
|
24
|
+
def key?(name)
|
25
|
+
KERNEL_RESPOND_TO.bind_call(@predicates, name)
|
26
26
|
end
|
27
27
|
|
28
28
|
# @api private
|
29
|
-
def
|
30
|
-
|
29
|
+
def [](name)
|
30
|
+
predicates[name]
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Types
|
5
|
+
# @api private
|
6
|
+
class Printer
|
7
|
+
# @api private
|
8
|
+
class Composition
|
9
|
+
def initialize(printer, composition_class)
|
10
|
+
@printer = printer
|
11
|
+
@composition_class = composition_class
|
12
|
+
freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
def visit(composition)
|
16
|
+
visit_constructors(composition) do |constructors|
|
17
|
+
@printer.visit_options(composition.options, composition.meta) do |opts|
|
18
|
+
yield "#{@composition_class.composition_name}<#{constructors}#{opts}>"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def visit_constructors(composition)
|
26
|
+
visit_constructor(composition.left) do |left|
|
27
|
+
visit_constructor(composition.right) do |right|
|
28
|
+
yield "#{left} #{@composition_class.operator} #{right}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def visit_constructor(type, &block)
|
34
|
+
case type
|
35
|
+
when @composition_class
|
36
|
+
visit_constructors(type, &block)
|
37
|
+
else
|
38
|
+
@printer.visit(type, &block)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|