dry-types 0.15.0 → 1.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +18 -2
- data/.travis.yml +4 -5
- data/.yardopts +6 -2
- data/CHANGELOG.md +69 -1
- data/Gemfile +3 -0
- data/README.md +2 -1
- data/Rakefile +2 -0
- data/benchmarks/hash_schemas.rb +2 -0
- data/benchmarks/lax_schema.rb +16 -0
- data/benchmarks/profile_invalid_input.rb +15 -0
- data/benchmarks/profile_lax_schema_valid.rb +16 -0
- data/benchmarks/profile_valid_input.rb +15 -0
- data/benchmarks/schema_valid_vs_invalid.rb +21 -0
- data/benchmarks/setup.rb +17 -0
- data/dry-types.gemspec +4 -2
- data/lib/dry-types.rb +2 -0
- data/lib/dry/types.rb +51 -13
- data/lib/dry/types/any.rb +21 -10
- data/lib/dry/types/array.rb +11 -1
- data/lib/dry/types/array/member.rb +65 -13
- data/lib/dry/types/builder.rb +48 -4
- data/lib/dry/types/builder_methods.rb +9 -8
- data/lib/dry/types/coercions.rb +71 -19
- data/lib/dry/types/coercions/json.rb +22 -3
- data/lib/dry/types/coercions/params.rb +98 -30
- data/lib/dry/types/compiler.rb +35 -12
- data/lib/dry/types/constrained.rb +73 -27
- data/lib/dry/types/constrained/coercible.rb +36 -6
- data/lib/dry/types/constraints.rb +15 -1
- data/lib/dry/types/constructor.rb +90 -43
- data/lib/dry/types/constructor/function.rb +201 -0
- data/lib/dry/types/container.rb +5 -0
- data/lib/dry/types/core.rb +7 -5
- data/lib/dry/types/decorator.rb +36 -9
- data/lib/dry/types/default.rb +48 -16
- data/lib/dry/types/enum.rb +30 -16
- data/lib/dry/types/errors.rb +73 -7
- data/lib/dry/types/extensions.rb +2 -0
- data/lib/dry/types/extensions/maybe.rb +43 -4
- data/lib/dry/types/fn_container.rb +5 -0
- data/lib/dry/types/hash.rb +22 -3
- data/lib/dry/types/hash/constructor.rb +13 -0
- data/lib/dry/types/inflector.rb +2 -0
- data/lib/dry/types/json.rb +4 -6
- data/lib/dry/types/{safe.rb → lax.rb} +34 -17
- data/lib/dry/types/map.rb +63 -29
- data/lib/dry/types/meta.rb +51 -0
- data/lib/dry/types/module.rb +7 -2
- data/lib/dry/types/nominal.rb +105 -13
- data/lib/dry/types/options.rb +12 -25
- data/lib/dry/types/params.rb +5 -3
- data/lib/dry/types/printable.rb +5 -1
- data/lib/dry/types/printer.rb +58 -57
- data/lib/dry/types/result.rb +26 -0
- data/lib/dry/types/schema.rb +169 -66
- data/lib/dry/types/schema/key.rb +34 -39
- data/lib/dry/types/spec/types.rb +41 -1
- data/lib/dry/types/sum.rb +70 -21
- data/lib/dry/types/type.rb +49 -0
- data/lib/dry/types/version.rb +3 -1
- metadata +14 -12
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Types
|
5
|
+
# Storage for meta-data
|
6
|
+
#
|
7
|
+
# @api public
|
8
|
+
module Meta
|
9
|
+
def initialize(*args, meta: EMPTY_HASH, **options)
|
10
|
+
super(*args, **options)
|
11
|
+
@meta = meta.freeze
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [Hash] new_options
|
15
|
+
#
|
16
|
+
# @return [Type]
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
def with(options)
|
20
|
+
super(meta: @meta, **options)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @overload meta
|
24
|
+
# @return [Hash] metadata associated with type
|
25
|
+
#
|
26
|
+
# @overload meta(data)
|
27
|
+
# @param [Hash] new metadata to merge into existing metadata
|
28
|
+
# @return [Type] new type with added metadata
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
def meta(data = nil)
|
32
|
+
if !data
|
33
|
+
@meta
|
34
|
+
elsif data.empty?
|
35
|
+
self
|
36
|
+
else
|
37
|
+
with(meta: @meta.merge(data))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Resets meta
|
42
|
+
#
|
43
|
+
# @return [Dry::Types::Type]
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
def pristine
|
47
|
+
with(meta: EMPTY_HASH)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/dry/types/module.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/core/deprecations'
|
2
4
|
require 'dry/types/builder_methods'
|
3
5
|
|
@@ -6,12 +8,15 @@ module Dry
|
|
6
8
|
# Export types registered in a container as module constants.
|
7
9
|
# @example
|
8
10
|
# module Types
|
9
|
-
# include Dry::Types
|
11
|
+
# include Dry::Types(:strict, :coercible, :nominal, default: :strict)
|
10
12
|
# end
|
11
|
-
#
|
13
|
+
#
|
14
|
+
# Types.constants
|
12
15
|
# # => [:Class, :Strict, :Symbol, :Integer, :Float, :String, :Array, :Hash,
|
13
16
|
# # :Decimal, :Nil, :True, :False, :Bool, :Date, :Nominal, :DateTime, :Range,
|
14
17
|
# # :Coercible, :Time]
|
18
|
+
#
|
19
|
+
# @api public
|
15
20
|
class Module < ::Module
|
16
21
|
def initialize(registry, *args)
|
17
22
|
@registry = registry
|
data/lib/dry/types/nominal.rb
CHANGED
@@ -1,13 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/core/deprecations'
|
2
4
|
require 'dry/types/builder'
|
3
5
|
require 'dry/types/result'
|
4
6
|
require 'dry/types/options'
|
7
|
+
require 'dry/types/meta'
|
5
8
|
|
6
9
|
module Dry
|
7
10
|
module Types
|
11
|
+
# Nominal types define a primitive class and do not apply any constructors or constraints
|
12
|
+
#
|
13
|
+
# Use these types for annotations and the base for building more complex types on top of them.
|
14
|
+
#
|
15
|
+
# @api public
|
8
16
|
class Nominal
|
9
17
|
include Type
|
10
18
|
include Options
|
19
|
+
include Meta
|
11
20
|
include Builder
|
12
21
|
include Printable
|
13
22
|
include Dry::Equalizer(:primitive, :options, :meta, inspect: false)
|
@@ -16,7 +25,10 @@ module Dry
|
|
16
25
|
attr_reader :primitive
|
17
26
|
|
18
27
|
# @param [Class] primitive
|
28
|
+
#
|
19
29
|
# @return [Type]
|
30
|
+
#
|
31
|
+
# @api private
|
20
32
|
def self.[](primitive)
|
21
33
|
if primitive == ::Array
|
22
34
|
Types::Array
|
@@ -27,8 +39,12 @@ module Dry
|
|
27
39
|
end
|
28
40
|
end
|
29
41
|
|
42
|
+
ALWAYS = proc { true }
|
43
|
+
|
30
44
|
# @param [Type,Class] primitive
|
31
45
|
# @param [Hash] options
|
46
|
+
#
|
47
|
+
# @api private
|
32
48
|
def initialize(primitive, **options)
|
33
49
|
super
|
34
50
|
@primitive = primitive
|
@@ -36,76 +52,152 @@ module Dry
|
|
36
52
|
end
|
37
53
|
|
38
54
|
# @return [String]
|
55
|
+
#
|
56
|
+
# @api public
|
39
57
|
def name
|
40
58
|
primitive.name
|
41
59
|
end
|
42
60
|
|
43
61
|
# @return [false]
|
62
|
+
#
|
63
|
+
# @api public
|
44
64
|
def default?
|
45
65
|
false
|
46
66
|
end
|
47
67
|
|
48
68
|
# @return [false]
|
69
|
+
#
|
70
|
+
# @api public
|
49
71
|
def constrained?
|
50
72
|
false
|
51
73
|
end
|
52
74
|
|
53
75
|
# @return [false]
|
76
|
+
#
|
77
|
+
# @api public
|
54
78
|
def optional?
|
55
79
|
false
|
56
80
|
end
|
57
81
|
|
58
82
|
# @param [BasicObject] input
|
83
|
+
#
|
84
|
+
# @return [BasicObject]
|
85
|
+
#
|
86
|
+
# @api private
|
87
|
+
def call_unsafe(input)
|
88
|
+
input
|
89
|
+
end
|
90
|
+
|
91
|
+
# @param [BasicObject] input
|
92
|
+
#
|
59
93
|
# @return [BasicObject]
|
60
|
-
|
94
|
+
#
|
95
|
+
# @api private
|
96
|
+
def call_safe(input)
|
61
97
|
input
|
62
98
|
end
|
63
|
-
alias_method :[], :call
|
64
99
|
|
65
100
|
# @param [Object] input
|
66
101
|
# @param [#call,nil] block
|
102
|
+
#
|
67
103
|
# @yieldparam [Failure] failure
|
68
104
|
# @yieldreturn [Result]
|
105
|
+
#
|
69
106
|
# @return [Result,Logic::Result] when a block is not provided
|
70
107
|
# @return [nil] otherwise
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
failure = failure(input, "#{input.inspect} must be an instance of #{primitive}")
|
76
|
-
block ? yield(failure) : failure
|
77
|
-
end
|
108
|
+
#
|
109
|
+
# @api public
|
110
|
+
def try(input)
|
111
|
+
success(input)
|
78
112
|
end
|
79
113
|
|
80
114
|
# @param (see Dry::Types::Success#initialize)
|
115
|
+
#
|
81
116
|
# @return [Result::Success]
|
117
|
+
#
|
118
|
+
# @api public
|
82
119
|
def success(input)
|
83
120
|
Result::Success.new(input)
|
84
121
|
end
|
85
122
|
|
86
123
|
# @param (see Failure#initialize)
|
124
|
+
#
|
87
125
|
# @return [Result::Failure]
|
126
|
+
#
|
127
|
+
# @api public
|
88
128
|
def failure(input, error)
|
129
|
+
unless error.is_a?(CoercionError)
|
130
|
+
raise ArgumentError, "error must be a CoercionError"
|
131
|
+
end
|
89
132
|
Result::Failure.new(input, error)
|
90
133
|
end
|
91
134
|
|
92
135
|
# Checks whether value is of a #primitive class
|
136
|
+
#
|
93
137
|
# @param [Object] value
|
138
|
+
#
|
94
139
|
# @return [Boolean]
|
140
|
+
#
|
141
|
+
# @api public
|
95
142
|
def primitive?(value)
|
96
143
|
value.is_a?(primitive)
|
97
144
|
end
|
98
|
-
|
99
|
-
|
145
|
+
|
146
|
+
# @api private
|
147
|
+
def coerce(input, &_block)
|
148
|
+
if primitive?(input)
|
149
|
+
input
|
150
|
+
elsif block_given?
|
151
|
+
yield
|
152
|
+
else
|
153
|
+
raise CoercionError, "#{input.inspect} must be an instance of #{primitive}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# @api private
|
158
|
+
def try_coerce(input)
|
159
|
+
result = success(input)
|
160
|
+
|
161
|
+
coerce(input) do
|
162
|
+
result = failure(
|
163
|
+
input,
|
164
|
+
CoercionError.new("#{input.inspect} must be an instance of #{primitive}")
|
165
|
+
)
|
166
|
+
end
|
167
|
+
|
168
|
+
if block_given?
|
169
|
+
yield(result)
|
170
|
+
else
|
171
|
+
result
|
172
|
+
end
|
173
|
+
end
|
100
174
|
|
101
175
|
# Return AST representation of a type nominal
|
102
176
|
#
|
103
|
-
# @api public
|
104
|
-
#
|
105
177
|
# @return [Array]
|
178
|
+
#
|
179
|
+
# @api public
|
106
180
|
def to_ast(meta: true)
|
107
181
|
[:nominal, [primitive, meta ? self.meta : EMPTY_HASH]]
|
108
182
|
end
|
183
|
+
|
184
|
+
# Return self. Nominal types are lax by definition
|
185
|
+
#
|
186
|
+
# @return [Nominal]
|
187
|
+
#
|
188
|
+
# @api public
|
189
|
+
def lax
|
190
|
+
self
|
191
|
+
end
|
192
|
+
|
193
|
+
# Wrap the type with a proc
|
194
|
+
#
|
195
|
+
# @return [Proc]
|
196
|
+
#
|
197
|
+
# @api public
|
198
|
+
def to_proc
|
199
|
+
ALWAYS
|
200
|
+
end
|
109
201
|
end
|
110
202
|
|
111
203
|
extend Dry::Core::Deprecations[:'dry-types']
|
data/lib/dry/types/options.rb
CHANGED
@@ -1,42 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dry
|
2
4
|
module Types
|
5
|
+
# Common API for types with options
|
6
|
+
#
|
7
|
+
# @api private
|
3
8
|
module Options
|
4
9
|
# @return [Hash]
|
5
10
|
attr_reader :options
|
6
11
|
|
7
12
|
# @see Nominal#initialize
|
8
|
-
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
def initialize(*args, **options)
|
9
16
|
@__args__ = args.freeze
|
10
17
|
@options = options.freeze
|
11
|
-
@meta = meta.freeze
|
12
18
|
end
|
13
19
|
|
14
20
|
# @param [Hash] new_options
|
21
|
+
#
|
15
22
|
# @return [Type]
|
16
|
-
def with(**new_options)
|
17
|
-
self.class.new(*@__args__, **options, meta: @meta, **new_options)
|
18
|
-
end
|
19
|
-
|
20
|
-
# @overload meta
|
21
|
-
# @return [Hash] metadata associated with type
|
22
23
|
#
|
23
|
-
# @
|
24
|
-
|
25
|
-
|
26
|
-
def meta(data = nil)
|
27
|
-
if !data
|
28
|
-
@meta
|
29
|
-
elsif data.empty?
|
30
|
-
self
|
31
|
-
else
|
32
|
-
with(meta: @meta.merge(data))
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Resets meta
|
37
|
-
# @return [Dry::Types::Type]
|
38
|
-
def pristine
|
39
|
-
with(meta: EMPTY_HASH)
|
24
|
+
# @api private
|
25
|
+
def with(**new_options)
|
26
|
+
self.class.new(*@__args__, **options, **new_options)
|
40
27
|
end
|
41
28
|
end
|
42
29
|
end
|
data/lib/dry/types/params.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'dry/types/coercions/params'
|
2
4
|
|
3
5
|
module Dry
|
@@ -27,7 +29,7 @@ module Dry
|
|
27
29
|
end
|
28
30
|
|
29
31
|
register('params.bool') do
|
30
|
-
|
32
|
+
self['params.true'] | self['params.false']
|
31
33
|
end
|
32
34
|
|
33
35
|
register('params.integer') do
|
@@ -43,11 +45,11 @@ module Dry
|
|
43
45
|
end
|
44
46
|
|
45
47
|
register('params.array') do
|
46
|
-
self['nominal.array'].constructor(Coercions::Params.method(:to_ary))
|
48
|
+
self['nominal.array'].constructor(Coercions::Params.method(:to_ary))
|
47
49
|
end
|
48
50
|
|
49
51
|
register('params.hash') do
|
50
|
-
self['nominal.hash'].constructor(Coercions::Params.method(:to_hash))
|
52
|
+
self['nominal.hash'].constructor(Coercions::Params.method(:to_hash))
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
data/lib/dry/types/printable.rb
CHANGED
data/lib/dry/types/printer.rb
CHANGED
@@ -16,7 +16,7 @@ module Dry
|
|
16
16
|
Map => :visit_map,
|
17
17
|
Array => :visit_array,
|
18
18
|
Array::Member => :visit_array_member,
|
19
|
-
|
19
|
+
Lax => :visit_lax,
|
20
20
|
Enum => :visit_enum,
|
21
21
|
Default => :visit_default,
|
22
22
|
Default::Callable => :visit_default,
|
@@ -28,7 +28,7 @@ module Dry
|
|
28
28
|
def call(type)
|
29
29
|
output = "".dup
|
30
30
|
visit(type) { |str| output << str }
|
31
|
-
"#<Dry::Types[#{
|
31
|
+
"#<Dry::Types[#{output}]>"
|
32
32
|
end
|
33
33
|
|
34
34
|
def visit(type, &block)
|
@@ -36,7 +36,7 @@ module Dry
|
|
36
36
|
if type.is_a?(Type)
|
37
37
|
return yield type.inspect
|
38
38
|
else
|
39
|
-
raise ArgumentError, "Do not know how to print #{
|
39
|
+
raise ArgumentError, "Do not know how to print #{type.class}"
|
40
40
|
end
|
41
41
|
end
|
42
42
|
send(print_with, type, &block)
|
@@ -52,18 +52,18 @@ module Dry
|
|
52
52
|
|
53
53
|
def visit_array_member(array)
|
54
54
|
visit(array.member) do |type|
|
55
|
-
yield "Array<#{
|
55
|
+
yield "Array<#{type}>"
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
59
|
def visit_constructor(constructor)
|
60
60
|
visit(constructor.type) do |type|
|
61
|
-
visit_callable(constructor.fn) do |fn|
|
61
|
+
visit_callable(constructor.fn.fn) do |fn|
|
62
62
|
options = constructor.options.dup
|
63
63
|
options.delete(:fn)
|
64
64
|
|
65
|
-
visit_options(options
|
66
|
-
yield "Constructor<#{
|
65
|
+
visit_options(options) do |opts|
|
66
|
+
yield "Constructor<#{type} fn=#{fn}#{opts}>"
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
@@ -74,8 +74,8 @@ module Dry
|
|
74
74
|
options = constrained.options.dup
|
75
75
|
rule = options.delete(:rule)
|
76
76
|
|
77
|
-
visit_options(options
|
78
|
-
yield "Constrained<#{
|
77
|
+
visit_options(options) do |opts|
|
78
|
+
yield "Constrained<#{type} rule=[#{rule}]>"
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
@@ -83,37 +83,38 @@ module Dry
|
|
83
83
|
def visit_schema(schema)
|
84
84
|
options = schema.options.dup
|
85
85
|
size = schema.count
|
86
|
-
key_fn_str =
|
87
|
-
type_fn_str =
|
88
|
-
strict_str =
|
86
|
+
key_fn_str = ''
|
87
|
+
type_fn_str = ''
|
88
|
+
strict_str = ''
|
89
89
|
|
90
|
-
strict_str =
|
90
|
+
strict_str = 'strict ' if options.delete(:strict)
|
91
91
|
|
92
92
|
if key_fn = options.delete(:key_transform_fn)
|
93
93
|
visit_callable(key_fn) do |fn|
|
94
|
-
key_fn_str = "key_fn=#{
|
94
|
+
key_fn_str = "key_fn=#{fn} "
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
98
|
if type_fn = options.delete(:type_transform_fn)
|
99
99
|
visit_callable(type_fn) do |fn|
|
100
|
-
type_fn_str = "type_fn=#{
|
100
|
+
type_fn_str = "type_fn=#{fn} "
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
104
|
keys = options.delete(:keys)
|
105
105
|
|
106
106
|
visit_options(options, schema.meta) do |opts|
|
107
|
-
|
107
|
+
opts = "#{opts[1..-1]} " unless opts.empty?
|
108
|
+
schema_parameters = "#{key_fn_str}#{type_fn_str}#{strict_str}#{opts}"
|
108
109
|
|
109
|
-
header = "Schema<#{
|
110
|
+
header = "Schema<#{schema_parameters}keys={"
|
110
111
|
|
111
112
|
if size.zero?
|
112
113
|
yield "#{ header}}>"
|
113
114
|
else
|
114
115
|
yield header.dup << keys.map { |key|
|
115
116
|
visit(key) { |type| type }
|
116
|
-
}.join(
|
117
|
+
}.join(' ') << '}>'
|
117
118
|
end
|
118
119
|
end
|
119
120
|
end
|
@@ -125,8 +126,8 @@ module Dry
|
|
125
126
|
options.delete(:key_type)
|
126
127
|
options.delete(:value_type)
|
127
128
|
|
128
|
-
visit_options(options
|
129
|
-
yield "Map<#{
|
129
|
+
visit_options(options) do |opts|
|
130
|
+
yield "Map<#{key} => #{value}>"
|
130
131
|
end
|
131
132
|
end
|
132
133
|
end
|
@@ -135,9 +136,9 @@ module Dry
|
|
135
136
|
def visit_key(key)
|
136
137
|
visit(key.type) do |type|
|
137
138
|
if key.required?
|
138
|
-
yield "#{
|
139
|
+
yield "#{key.name}: #{type}"
|
139
140
|
else
|
140
|
-
yield "#{
|
141
|
+
yield "#{key.name}?: #{type}"
|
141
142
|
end
|
142
143
|
end
|
143
144
|
end
|
@@ -145,7 +146,7 @@ module Dry
|
|
145
146
|
def visit_sum(sum)
|
146
147
|
visit_sum_constructors(sum) do |constructors|
|
147
148
|
visit_options(sum.options, sum.meta) do |opts|
|
148
|
-
yield "Sum<#{
|
149
|
+
yield "Sum<#{constructors}#{opts}>"
|
149
150
|
end
|
150
151
|
end
|
151
152
|
end
|
@@ -157,11 +158,11 @@ module Dry
|
|
157
158
|
case sum.right
|
158
159
|
when Sum
|
159
160
|
visit_sum_constructors(sum.right) do |right|
|
160
|
-
yield "#{
|
161
|
+
yield "#{left} | #{right}"
|
161
162
|
end
|
162
163
|
else
|
163
164
|
visit(sum.right) do |right|
|
164
|
-
yield "#{
|
165
|
+
yield "#{left} | #{right}"
|
165
166
|
end
|
166
167
|
end
|
167
168
|
end
|
@@ -170,11 +171,11 @@ module Dry
|
|
170
171
|
case sum.right
|
171
172
|
when Sum
|
172
173
|
visit_sum_constructors(sum.right) do |right|
|
173
|
-
yield "#{
|
174
|
+
yield "#{left} | #{right}"
|
174
175
|
end
|
175
176
|
else
|
176
177
|
visit(sum.right) do |right|
|
177
|
-
yield "#{
|
178
|
+
yield "#{left} | #{right}"
|
178
179
|
end
|
179
180
|
end
|
180
181
|
end
|
@@ -186,15 +187,15 @@ module Dry
|
|
186
187
|
options = enum.options.dup
|
187
188
|
mapping = options.delete(:mapping)
|
188
189
|
|
189
|
-
visit_options(options
|
190
|
+
visit_options(options) do |opts|
|
190
191
|
if mapping == enum.inverted_mapping
|
191
|
-
values = mapping.values.map(&:inspect).join(
|
192
|
-
yield "Enum<#{
|
192
|
+
values = mapping.values.map(&:inspect).join(', ')
|
193
|
+
yield "Enum<#{type} values={#{values}}#{opts}>"
|
193
194
|
else
|
194
195
|
mapping_str = mapping.map { |key, value|
|
195
|
-
"#{ key.inspect }=>#{
|
196
|
-
}.join(
|
197
|
-
yield "Enum<#{
|
196
|
+
"#{ key.inspect }=>#{value.inspect}"
|
197
|
+
}.join(', ')
|
198
|
+
yield "Enum<#{type} mapping={#{mapping_str}}#{opts}>"
|
198
199
|
end
|
199
200
|
end
|
200
201
|
end
|
@@ -202,13 +203,13 @@ module Dry
|
|
202
203
|
|
203
204
|
def visit_default(default)
|
204
205
|
visit(default.type) do |type|
|
205
|
-
visit_options(default.options
|
206
|
+
visit_options(default.options) do |opts|
|
206
207
|
if default.is_a?(Default::Callable)
|
207
208
|
visit_callable(default.value) do |fn|
|
208
|
-
yield "Default<#{
|
209
|
+
yield "Default<#{type} value_fn=#{fn}#{opts}>"
|
209
210
|
end
|
210
211
|
else
|
211
|
-
yield "Default<#{
|
212
|
+
yield "Default<#{type} value=#{default.value.inspect}#{opts}>"
|
212
213
|
end
|
213
214
|
end
|
214
215
|
end
|
@@ -216,31 +217,31 @@ module Dry
|
|
216
217
|
|
217
218
|
def visit_nominal(type)
|
218
219
|
visit_options(type.options, type.meta) do |opts|
|
219
|
-
yield "Nominal<#{
|
220
|
+
yield "Nominal<#{type.primitive}#{opts}>"
|
220
221
|
end
|
221
222
|
end
|
222
223
|
|
223
|
-
def
|
224
|
-
visit(
|
225
|
-
yield "
|
224
|
+
def visit_lax(lax)
|
225
|
+
visit(lax.type) do |type|
|
226
|
+
yield "Lax<#{type}>"
|
226
227
|
end
|
227
228
|
end
|
228
229
|
|
229
230
|
def visit_hash(hash)
|
230
231
|
options = hash.options.dup
|
231
|
-
type_fn_str =
|
232
|
+
type_fn_str = ''
|
232
233
|
|
233
234
|
if type_fn = options.delete(:type_transform_fn)
|
234
235
|
visit_callable(type_fn) do |fn|
|
235
|
-
type_fn_str = "type_fn=#{
|
236
|
+
type_fn_str = "type_fn=#{fn}"
|
236
237
|
end
|
237
238
|
end
|
238
239
|
|
239
240
|
visit_options(options, hash.meta) do |opts|
|
240
241
|
if opts.empty? && type_fn_str.empty?
|
241
|
-
yield
|
242
|
+
yield 'Hash'
|
242
243
|
else
|
243
|
-
yield "Hash<#{
|
244
|
+
yield "Hash<#{type_fn_str}#{opts}>"
|
244
245
|
end
|
245
246
|
end
|
246
247
|
end
|
@@ -255,36 +256,36 @@ module Dry
|
|
255
256
|
path, line = fn.source_location
|
256
257
|
|
257
258
|
if line && line.zero?
|
258
|
-
yield ".#{
|
259
|
+
yield ".#{path}"
|
259
260
|
elsif path
|
260
|
-
yield "#{
|
261
|
+
yield "#{path.sub(Dir.pwd + '/', EMPTY_STRING) }:#{line}"
|
261
262
|
elsif fn.lambda?
|
262
|
-
yield
|
263
|
+
yield '(lambda)'
|
263
264
|
else
|
264
265
|
match = fn.to_s.match(/\A#<Proc:0x\h+\(&:(\w+)\)>\z/)
|
265
266
|
|
266
267
|
if match
|
267
|
-
yield ".#{
|
268
|
+
yield ".#{match[1]}"
|
268
269
|
else
|
269
|
-
yield
|
270
|
+
yield '(proc)'
|
270
271
|
end
|
271
272
|
end
|
272
273
|
else
|
273
274
|
call = fn.method(:call)
|
274
275
|
|
275
276
|
if call.owner == fn.class
|
276
|
-
yield "#{
|
277
|
+
yield "#{fn.class}#call"
|
277
278
|
else
|
278
|
-
yield "#{
|
279
|
+
yield "#{fn}.call"
|
279
280
|
end
|
280
281
|
end
|
281
282
|
end
|
282
283
|
|
283
|
-
def visit_options(options, meta)
|
284
|
+
def visit_options(options, meta = EMPTY_HASH)
|
284
285
|
if options.empty? && meta.empty?
|
285
|
-
yield
|
286
|
+
yield ''
|
286
287
|
else
|
287
|
-
opts = options.empty? ?
|
288
|
+
opts = options.empty? ? '' : " options=#{options.inspect}"
|
288
289
|
|
289
290
|
if meta.empty?
|
290
291
|
yield opts
|
@@ -292,13 +293,13 @@ module Dry
|
|
292
293
|
values = meta.map do |key, value|
|
293
294
|
case key
|
294
295
|
when Symbol
|
295
|
-
"#{
|
296
|
+
"#{key}: #{value.inspect}"
|
296
297
|
else
|
297
|
-
"#{
|
298
|
+
"#{key.inspect}=>#{value.inspect}"
|
298
299
|
end
|
299
300
|
end
|
300
301
|
|
301
|
-
yield "#{
|
302
|
+
yield "#{opts} meta={#{values.join(', ')}}"
|
302
303
|
end
|
303
304
|
end
|
304
305
|
end
|