bcdd-result 0.9.1 → 0.11.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/.rubocop.yml +8 -0
- data/CHANGELOG.md +43 -16
- data/README.md +259 -40
- data/Rakefile +8 -2
- data/Steepfile +2 -2
- data/lib/bcdd/result/config/switchers/addons.rb +25 -0
- data/lib/bcdd/result/config/{constant_alias.rb → switchers/constant_aliases.rb} +4 -4
- data/lib/bcdd/result/config/switchers/features.rb +28 -0
- data/lib/bcdd/result/config/switchers/pattern_matching.rb +20 -0
- data/lib/bcdd/result/config.rb +8 -28
- data/lib/bcdd/result/context/expectations/mixin.rb +10 -2
- data/lib/bcdd/result/context/mixin.rb +13 -5
- data/lib/bcdd/result/context/success.rb +2 -2
- data/lib/bcdd/result/context.rb +10 -15
- data/lib/bcdd/result/expectations/mixin.rb +11 -5
- data/lib/bcdd/result/expectations.rb +6 -6
- data/lib/bcdd/result/mixin.rb +11 -5
- data/lib/bcdd/result/transitions/tracking/disabled.rb +17 -0
- data/lib/bcdd/result/transitions/tracking/enabled.rb +80 -0
- data/lib/bcdd/result/transitions/tracking.rb +20 -0
- data/lib/bcdd/result/transitions/tree.rb +95 -0
- data/lib/bcdd/result/transitions.rb +30 -0
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +33 -22
- data/sig/bcdd/result/config.rbs +101 -0
- data/sig/bcdd/result/context.rbs +114 -0
- data/sig/bcdd/result/contract.rbs +119 -0
- data/sig/bcdd/result/data.rbs +16 -0
- data/sig/bcdd/result/error.rbs +31 -0
- data/sig/bcdd/result/expectations.rbs +71 -0
- data/sig/bcdd/result/handler.rbs +47 -0
- data/sig/bcdd/result/mixin.rbs +45 -0
- data/sig/bcdd/result/transitions.rbs +89 -0
- data/sig/bcdd/result/version.rbs +5 -0
- data/sig/bcdd/result.rbs +7 -519
- metadata +22 -4
data/lib/bcdd/result.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'result/version'
|
4
|
+
require_relative 'result/transitions'
|
4
5
|
require_relative 'result/error'
|
5
6
|
require_relative 'result/data'
|
6
7
|
require_relative 'result/handler'
|
@@ -13,13 +14,13 @@ require_relative 'result/context'
|
|
13
14
|
require_relative 'result/config'
|
14
15
|
|
15
16
|
class BCDD::Result
|
16
|
-
attr_accessor :unknown
|
17
|
+
attr_accessor :unknown, :transitions
|
17
18
|
|
18
|
-
attr_reader :subject, :data, :type_checker, :
|
19
|
+
attr_reader :subject, :data, :type_checker, :terminal
|
19
20
|
|
20
21
|
protected :subject
|
21
22
|
|
22
|
-
private :unknown, :unknown=, :type_checker
|
23
|
+
private :unknown, :unknown=, :type_checker, :transitions=
|
23
24
|
|
24
25
|
def self.config
|
25
26
|
Config.instance
|
@@ -31,19 +32,22 @@ class BCDD::Result
|
|
31
32
|
config.freeze
|
32
33
|
end
|
33
34
|
|
34
|
-
def initialize(type:, value:, subject: nil, expectations: nil,
|
35
|
+
def initialize(type:, value:, subject: nil, expectations: nil, terminal: nil)
|
35
36
|
data = Data.new(kind, type, value)
|
36
37
|
|
37
38
|
@type_checker = Contract.evaluate(data, expectations)
|
38
39
|
@subject = subject
|
39
|
-
@
|
40
|
+
@terminal = terminal || kind == :failure
|
40
41
|
@data = data
|
41
42
|
|
42
43
|
self.unknown = true
|
44
|
+
self.transitions = Transitions::Tracking::EMPTY
|
45
|
+
|
46
|
+
Transitions.tracking.record(self)
|
43
47
|
end
|
44
48
|
|
45
|
-
def
|
46
|
-
|
49
|
+
def terminal?
|
50
|
+
terminal
|
47
51
|
end
|
48
52
|
|
49
53
|
def type
|
@@ -85,7 +89,7 @@ class BCDD::Result
|
|
85
89
|
end
|
86
90
|
|
87
91
|
def and_then(method_name = nil, context = nil, &block)
|
88
|
-
return self if
|
92
|
+
return self if terminal?
|
89
93
|
|
90
94
|
method_name && block and raise ::ArgumentError, 'method_name and block are mutually exclusive'
|
91
95
|
|
@@ -135,28 +139,35 @@ class BCDD::Result
|
|
135
139
|
block.call(value, type)
|
136
140
|
end
|
137
141
|
|
138
|
-
def call_and_then_subject_method(method_name,
|
142
|
+
def call_and_then_subject_method(method_name, context_data)
|
139
143
|
method = subject.method(method_name)
|
140
144
|
|
141
|
-
|
142
|
-
|
143
|
-
when 0 then subject.send(method_name)
|
144
|
-
when 1 then subject.send(method_name, value)
|
145
|
-
when 2 then subject.send(method_name, value, context)
|
146
|
-
else raise Error::InvalidSubjectMethodArity.build(subject: subject, method: method, max_arity: 2)
|
147
|
-
end
|
145
|
+
Transitions.tracking.record_and_then(method, context_data, subject) do
|
146
|
+
result = call_and_then_subject_method!(method, context_data)
|
148
147
|
|
149
|
-
|
148
|
+
ensure_result_object(result, origin: :method)
|
149
|
+
end
|
150
150
|
end
|
151
151
|
|
152
|
-
def
|
153
|
-
|
152
|
+
def call_and_then_subject_method!(method, context_data)
|
153
|
+
case method.arity
|
154
|
+
when 0 then subject.send(method.name)
|
155
|
+
when 1 then subject.send(method.name, value)
|
156
|
+
when 2 then subject.send(method.name, value, context_data)
|
157
|
+
else raise Error::InvalidSubjectMethodArity.build(subject: subject, method: method, max_arity: 2)
|
158
|
+
end
|
154
159
|
end
|
155
160
|
|
156
|
-
def call_and_then_block
|
157
|
-
|
161
|
+
def call_and_then_block(block)
|
162
|
+
Transitions.tracking.record_and_then(:block, nil, subject) do
|
163
|
+
result = call_and_then_block!(block)
|
164
|
+
|
165
|
+
ensure_result_object(result, origin: :block)
|
166
|
+
end
|
167
|
+
end
|
158
168
|
|
159
|
-
|
169
|
+
def call_and_then_block!(block)
|
170
|
+
block.call(value)
|
160
171
|
end
|
161
172
|
|
162
173
|
def ensure_result_object(result, origin:)
|
@@ -0,0 +1,101 @@
|
|
1
|
+
class BCDD::Result::Config
|
2
|
+
include Singleton
|
3
|
+
|
4
|
+
ADDON: Hash[Symbol, Hash[Symbol, untyped]]
|
5
|
+
FEATURE: Hash[Symbol, Hash[Symbol, untyped]]
|
6
|
+
PATTERN_MATCHING: Hash[Symbol, Hash[Symbol, untyped]]
|
7
|
+
|
8
|
+
attr_reader addon: BCDD::Result::Config::Switcher
|
9
|
+
attr_reader feature: BCDD::Result::Config::Switcher
|
10
|
+
attr_reader constant_alias: BCDD::Result::Config::Switcher
|
11
|
+
attr_reader pattern_matching: BCDD::Result::Config::Switcher
|
12
|
+
|
13
|
+
def self.instance: -> BCDD::Result::Config
|
14
|
+
|
15
|
+
def initialize: -> void
|
16
|
+
|
17
|
+
def freeze: -> BCDD::Result::Config
|
18
|
+
def options: -> Hash[Symbol, BCDD::Result::Config::Switcher]
|
19
|
+
def to_h: -> Hash[Symbol, Hash[Symbol | String, bool]]
|
20
|
+
end
|
21
|
+
|
22
|
+
module BCDD::Result::Config::Options
|
23
|
+
def self.with_defaults: (
|
24
|
+
Hash[Symbol, Hash[Symbol, bool]],
|
25
|
+
Symbol
|
26
|
+
) -> Hash[Symbol, bool]
|
27
|
+
|
28
|
+
def self.select: (
|
29
|
+
Hash[Symbol, Hash[Symbol, bool]],
|
30
|
+
config: Symbol,
|
31
|
+
from: Hash[Symbol, untyped]
|
32
|
+
) -> Hash[Symbol, untyped]
|
33
|
+
|
34
|
+
def self.addon: (
|
35
|
+
map: Hash[Symbol, Hash[Symbol, bool]],
|
36
|
+
from: Hash[Symbol, Module]
|
37
|
+
) -> Hash[Symbol, Module]
|
38
|
+
end
|
39
|
+
|
40
|
+
class BCDD::Result::Config::Switcher
|
41
|
+
private attr_reader _affects: Hash[Symbol | String, Array[String]]
|
42
|
+
private attr_reader _options: Hash[Symbol | String, bool]
|
43
|
+
private attr_reader listener: Proc
|
44
|
+
|
45
|
+
def initialize: (
|
46
|
+
options: Hash[Symbol | String, Hash[Symbol, untyped]],
|
47
|
+
?listener: Proc
|
48
|
+
) -> void
|
49
|
+
|
50
|
+
def freeze: -> BCDD::Result::Config::Switcher
|
51
|
+
|
52
|
+
def to_h: -> Hash[Symbol | String, bool]
|
53
|
+
|
54
|
+
def options: -> Hash[Symbol | String, Hash[Symbol, untyped]]
|
55
|
+
|
56
|
+
def enabled?: (Symbol | String) -> bool
|
57
|
+
|
58
|
+
def enable!: (*(Symbol | String)) -> Hash[Symbol | String, Hash[Symbol, untyped]]
|
59
|
+
|
60
|
+
def disable!: (*(Symbol | String)) -> Hash[Symbol | String, Hash[Symbol, untyped]]
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def set_many: (Array[Symbol | String], to: bool) -> Hash[Symbol | String, Hash[Symbol, untyped]]
|
65
|
+
|
66
|
+
def set_one: (Symbol | String, bool) -> void
|
67
|
+
|
68
|
+
def require_option!: (Array[Symbol | String]) -> void
|
69
|
+
|
70
|
+
def validate_option!: (Symbol | String) -> void
|
71
|
+
|
72
|
+
def available_options_message: -> String
|
73
|
+
end
|
74
|
+
|
75
|
+
module BCDD::Result::Config::Addons
|
76
|
+
AFFECTS: Array[String]
|
77
|
+
OPTIONS: Hash[String, Hash[Symbol, untyped]]
|
78
|
+
|
79
|
+
def self.switcher: -> BCDD::Result::Config::Switcher
|
80
|
+
end
|
81
|
+
|
82
|
+
module BCDD::Result::Config::ConstantAliases
|
83
|
+
MAPPING: Hash[String, Hash[Symbol, untyped]]
|
84
|
+
OPTIONS: Hash[String, Hash[Symbol, untyped]]
|
85
|
+
Listener: Proc
|
86
|
+
|
87
|
+
def self.switcher: -> BCDD::Result::Config::Switcher
|
88
|
+
end
|
89
|
+
|
90
|
+
module BCDD::Result::Config::Features
|
91
|
+
OPTIONS: Hash[String, Hash[Symbol, untyped]]
|
92
|
+
Listener: Proc
|
93
|
+
|
94
|
+
def self.switcher: -> BCDD::Result::Config::Switcher
|
95
|
+
end
|
96
|
+
|
97
|
+
module BCDD::Result::Config::PatternMatching
|
98
|
+
OPTIONS: Hash[String, Hash[Symbol, untyped]]
|
99
|
+
|
100
|
+
def self.switcher: -> BCDD::Result::Config::Switcher
|
101
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
class BCDD::Result::Context < BCDD::Result
|
2
|
+
EXPECTED_OUTCOME: String
|
3
|
+
|
4
|
+
SubjectMethodArity: ^(Method) -> Integer
|
5
|
+
|
6
|
+
attr_reader acc: Hash[Symbol, untyped]
|
7
|
+
|
8
|
+
def initialize: (
|
9
|
+
type: Symbol,
|
10
|
+
value: untyped,
|
11
|
+
?subject: untyped,
|
12
|
+
?expectations: BCDD::Result::Contract::Evaluator,
|
13
|
+
?terminal: bool
|
14
|
+
) -> void
|
15
|
+
|
16
|
+
def and_then: (?Symbol, **untyped) ?{ (Hash[Symbol, untyped]) -> untyped } -> BCDD::Result::Context
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def call_and_then_subject_method: (Symbol, Hash[Symbol, untyped]) -> BCDD::Result::Context
|
21
|
+
def ensure_result_object: (untyped, origin: Symbol) -> BCDD::Result::Context
|
22
|
+
|
23
|
+
def raise_unexpected_outcome_error: (BCDD::Result::Context | untyped, Symbol) -> void
|
24
|
+
end
|
25
|
+
|
26
|
+
class BCDD::Result::Context
|
27
|
+
class Success < BCDD::Result::Context
|
28
|
+
include BCDD::Result::Success::Methods
|
29
|
+
|
30
|
+
def and_expose: (Symbol, Array[Symbol], terminal: bool) -> BCDD::Result::Context::Success
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.Success: (Symbol, **untyped) -> BCDD::Result::Context::Success
|
34
|
+
end
|
35
|
+
|
36
|
+
class BCDD::Result::Context
|
37
|
+
class Failure < BCDD::Result::Context
|
38
|
+
include BCDD::Result::Failure::Methods
|
39
|
+
|
40
|
+
def and_expose: (Symbol, Array[Symbol], **untyped) -> BCDD::Result::Context::Failure
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.Failure: (Symbol, **untyped) -> BCDD::Result::Context::Failure
|
44
|
+
end
|
45
|
+
|
46
|
+
class BCDD::Result::Context
|
47
|
+
module Mixin
|
48
|
+
Factory: singleton(BCDD::Result::Mixin::Factory)
|
49
|
+
|
50
|
+
module Methods
|
51
|
+
def Success: (Symbol, **untyped) -> BCDD::Result::Context::Success
|
52
|
+
|
53
|
+
def Failure: (Symbol, **untyped) -> BCDD::Result::Context::Failure
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def _ResultAs: (singleton(BCDD::Result::Context), Symbol, untyped, ?terminal: bool) -> untyped
|
58
|
+
end
|
59
|
+
|
60
|
+
module Addons
|
61
|
+
module Continue
|
62
|
+
include BCDD::Result::Context::Mixin::Methods
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def Continue: (**untyped) -> BCDD::Result::Context::Success
|
67
|
+
end
|
68
|
+
|
69
|
+
module Given
|
70
|
+
include BCDD::Result::Context::Mixin::Methods
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def Given: (*untyped) -> BCDD::Result::Context::Success
|
75
|
+
end
|
76
|
+
|
77
|
+
OPTIONS: Hash[Symbol, Module]
|
78
|
+
|
79
|
+
def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.mixin_module: -> singleton(BCDD::Result::Context::Mixin)
|
84
|
+
|
85
|
+
def self.result_factory: -> singleton(BCDD::Result::Context)
|
86
|
+
end
|
87
|
+
|
88
|
+
class BCDD::Result::Context::Expectations < BCDD::Result::Expectations
|
89
|
+
def self.mixin_module: -> singleton(BCDD::Result::Context::Expectations::Mixin)
|
90
|
+
|
91
|
+
def self.result_factory_without_expectations: -> singleton(BCDD::Result)
|
92
|
+
|
93
|
+
def Success: (Symbol, **untyped) -> BCDD::Result::Context::Success
|
94
|
+
def Failure: (Symbol, **untyped) -> BCDD::Result::Context::Failure
|
95
|
+
end
|
96
|
+
|
97
|
+
module BCDD::Result::Context::Expectations::Mixin
|
98
|
+
Methods: singleton(BCDD::Result::Expectations::Mixin::Methods)
|
99
|
+
Factory: singleton(BCDD::Result::Expectations::Mixin::Factory)
|
100
|
+
|
101
|
+
module Addons
|
102
|
+
module Continue
|
103
|
+
private def Continue: (**untyped) -> BCDD::Result::Context::Success
|
104
|
+
end
|
105
|
+
|
106
|
+
module Given
|
107
|
+
private def Given: (*untyped) -> BCDD::Result::Context::Success
|
108
|
+
end
|
109
|
+
|
110
|
+
OPTIONS: Hash[Symbol, Module]
|
111
|
+
|
112
|
+
def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module BCDD::Result::Contract
|
2
|
+
NONE: BCDD::Result::Contract::Evaluator
|
3
|
+
|
4
|
+
def self.evaluate: (
|
5
|
+
BCDD::Result::Data,
|
6
|
+
BCDD::Result::Contract::Evaluator
|
7
|
+
) -> BCDD::Result::Contract::TypeChecker
|
8
|
+
|
9
|
+
ToEnsure: ^(Hash[Symbol, untyped] | Array[Symbol], Hash[Symbol, Hash[Symbol, bool]])
|
10
|
+
-> BCDD::Result::Contract::Interface
|
11
|
+
|
12
|
+
def self.new: (
|
13
|
+
success: Hash[Symbol, untyped] | Array[Symbol],
|
14
|
+
failure: Hash[Symbol, untyped] | Array[Symbol],
|
15
|
+
config: Hash[Symbol, Hash[Symbol, bool]]
|
16
|
+
) -> BCDD::Result::Contract::Evaluator
|
17
|
+
end
|
18
|
+
|
19
|
+
module BCDD::Result::Contract
|
20
|
+
class TypeChecker
|
21
|
+
attr_reader result_type: Symbol
|
22
|
+
attr_reader expectations: BCDD::Result::Contract::Evaluator
|
23
|
+
|
24
|
+
def initialize: (
|
25
|
+
Symbol,
|
26
|
+
expectations: BCDD::Result::Contract::Evaluator
|
27
|
+
) -> void
|
28
|
+
|
29
|
+
def allow?: (Array[Symbol]) -> bool
|
30
|
+
def allow_success?: (Array[Symbol]) -> bool
|
31
|
+
def allow_failure?: (Array[Symbol]) -> bool
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def validate: (
|
36
|
+
Array[Symbol],
|
37
|
+
expected: BCDD::Result::Contract::Interface,
|
38
|
+
allow_empty: bool
|
39
|
+
) -> bool
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class BCDD::Result::Contract::Error < BCDD::Result::Error
|
44
|
+
class UnexpectedType < BCDD::Result::Contract::Error
|
45
|
+
def self.build: (type: Symbol, allowed_types: Set[Symbol])
|
46
|
+
-> BCDD::Result::Contract::Error::UnexpectedType
|
47
|
+
end
|
48
|
+
|
49
|
+
class UnexpectedValue < BCDD::Result::Contract::Error
|
50
|
+
def self.build: (type: Symbol, value: untyped, ?cause: Exception)
|
51
|
+
-> BCDD::Result::Contract::Error::UnexpectedValue
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module BCDD::Result::Contract
|
56
|
+
module Interface
|
57
|
+
def ==: (BCDD::Result::Contract::Interface) -> bool
|
58
|
+
|
59
|
+
def allowed_types: -> Set[Symbol]
|
60
|
+
|
61
|
+
def type?: (Symbol) -> bool
|
62
|
+
|
63
|
+
def type!: (Symbol) -> Symbol
|
64
|
+
|
65
|
+
def type_and_value!: (BCDD::Result::Data) -> void
|
66
|
+
|
67
|
+
def !=: (untyped) -> bool
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
module BCDD::Result::Contract
|
72
|
+
module Disabled
|
73
|
+
extend Interface
|
74
|
+
|
75
|
+
EMPTY_SET: Set[Symbol]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module BCDD::Result::Contract
|
80
|
+
class ForTypes
|
81
|
+
include Interface
|
82
|
+
|
83
|
+
def initialize: (Array[Symbol]) -> void
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
module BCDD::Result::Contract
|
88
|
+
class ForTypesAndValues
|
89
|
+
include Interface
|
90
|
+
|
91
|
+
def initialize: (
|
92
|
+
Hash[Symbol, untyped],
|
93
|
+
Hash[Symbol, Hash[Symbol, bool]]
|
94
|
+
) -> void
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def nil_as_valid_value_checking?: -> bool
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
module BCDD::Result::Contract
|
103
|
+
class Evaluator
|
104
|
+
include Interface
|
105
|
+
|
106
|
+
attr_reader allowed_types: Set[Symbol]
|
107
|
+
attr_reader success: BCDD::Result::Contract::Interface
|
108
|
+
attr_reader failure: BCDD::Result::Contract::Interface
|
109
|
+
|
110
|
+
def initialize: (
|
111
|
+
BCDD::Result::Contract::Interface,
|
112
|
+
BCDD::Result::Contract::Interface
|
113
|
+
) -> void
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def for: (BCDD::Result::Data) -> BCDD::Result::Contract::Interface
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class BCDD::Result
|
2
|
+
class Data
|
3
|
+
attr_reader kind: Symbol
|
4
|
+
attr_reader type: Symbol
|
5
|
+
attr_reader value: untyped
|
6
|
+
attr_reader to_h: Hash[Symbol, untyped]
|
7
|
+
attr_reader to_a: [Symbol, Symbol, untyped]
|
8
|
+
|
9
|
+
def initialize: (Symbol, Symbol, untyped) -> void
|
10
|
+
|
11
|
+
def inspect: -> String
|
12
|
+
|
13
|
+
alias to_ary to_a
|
14
|
+
alias to_hash to_h
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class BCDD::Result
|
2
|
+
class Error < StandardError
|
3
|
+
def self.build: (**untyped) -> BCDD::Result::Error
|
4
|
+
|
5
|
+
class NotImplemented < BCDD::Result::Error
|
6
|
+
end
|
7
|
+
|
8
|
+
class MissingTypeArgument < BCDD::Result::Error
|
9
|
+
end
|
10
|
+
|
11
|
+
class UnexpectedOutcome < BCDD::Result::Error
|
12
|
+
def self.build: (outcome: untyped, origin: Symbol, ?expected: String)
|
13
|
+
-> BCDD::Result::Error::UnexpectedOutcome
|
14
|
+
end
|
15
|
+
|
16
|
+
class InvalidResultSubject < BCDD::Result::Error
|
17
|
+
def self.build: (given_result: BCDD::Result, expected_subject: untyped)
|
18
|
+
-> BCDD::Result::Error::InvalidResultSubject
|
19
|
+
end
|
20
|
+
|
21
|
+
class InvalidSubjectMethodArity < BCDD::Result::Error
|
22
|
+
def self.build: (subject: untyped, method: Method, max_arity: Integer)
|
23
|
+
-> BCDD::Result::Error::InvalidSubjectMethodArity
|
24
|
+
end
|
25
|
+
|
26
|
+
class UnhandledTypes < BCDD::Result::Error
|
27
|
+
def self.build: (types: Set[Symbol])
|
28
|
+
-> BCDD::Result::Error::UnhandledTypes
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class BCDD::Result::Expectations
|
2
|
+
def self.mixin: (
|
3
|
+
?config: Hash[Symbol, Hash[Symbol, bool]],
|
4
|
+
?success: Hash[Symbol, untyped] | Array[Symbol],
|
5
|
+
?failure: Hash[Symbol, untyped] | Array[Symbol]
|
6
|
+
) -> Module
|
7
|
+
|
8
|
+
def self.mixin!: (
|
9
|
+
?config: Hash[Symbol, Hash[Symbol, bool]],
|
10
|
+
?success: Hash[Symbol, untyped] | Array[Symbol],
|
11
|
+
?failure: Hash[Symbol, untyped] | Array[Symbol]
|
12
|
+
) -> Module
|
13
|
+
|
14
|
+
def self.mixin_module: -> singleton(BCDD::Result::Expectations::Mixin)
|
15
|
+
|
16
|
+
def self.result_factory_without_expectations: -> singleton(BCDD::Result)
|
17
|
+
|
18
|
+
def self.new: (
|
19
|
+
?subject: untyped,
|
20
|
+
?contract: BCDD::Result::Contract::Evaluator,
|
21
|
+
?terminal: bool,
|
22
|
+
**untyped
|
23
|
+
) -> (BCDD::Result::Expectations | untyped)
|
24
|
+
|
25
|
+
def initialize: (
|
26
|
+
?subject: untyped,
|
27
|
+
?contract: BCDD::Result::Contract::Evaluator,
|
28
|
+
?terminal: bool,
|
29
|
+
**untyped
|
30
|
+
) -> void
|
31
|
+
|
32
|
+
def Success: (Symbol, ?untyped) -> BCDD::Result::Success
|
33
|
+
def Failure: (Symbol, ?untyped) -> BCDD::Result::Failure
|
34
|
+
|
35
|
+
def with: (subject: untyped) -> BCDD::Result::Expectations
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def _ResultAs: (singleton(BCDD::Result), Symbol, untyped) -> untyped
|
40
|
+
|
41
|
+
attr_reader subject: untyped
|
42
|
+
attr_reader contract: BCDD::Result::Contract::Evaluator
|
43
|
+
attr_reader terminal: bool
|
44
|
+
end
|
45
|
+
|
46
|
+
module BCDD::Result::Expectations::Mixin
|
47
|
+
module Factory
|
48
|
+
def self.module!: -> Module
|
49
|
+
end
|
50
|
+
|
51
|
+
module Methods
|
52
|
+
BASE: String
|
53
|
+
FACTORY: String
|
54
|
+
|
55
|
+
def self.to_eval: (Hash[Symbol, untyped]) -> String
|
56
|
+
end
|
57
|
+
|
58
|
+
module Addons
|
59
|
+
module Continue
|
60
|
+
private def Continue: (untyped) -> BCDD::Result::Success
|
61
|
+
end
|
62
|
+
|
63
|
+
module Given
|
64
|
+
private def Given: (untyped) -> BCDD::Result::Success
|
65
|
+
end
|
66
|
+
|
67
|
+
OPTIONS: Hash[Symbol, Module]
|
68
|
+
|
69
|
+
def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class BCDD::Result
|
2
|
+
class Handler
|
3
|
+
UNDEFINED: Object
|
4
|
+
|
5
|
+
def initialize: (
|
6
|
+
BCDD::Result,
|
7
|
+
type_checker: BCDD::Result::Contract::TypeChecker
|
8
|
+
) -> void
|
9
|
+
|
10
|
+
def []: (*Symbol) { (untyped, Symbol) -> void } -> untyped
|
11
|
+
def failure: (*Symbol) { (untyped, Symbol) -> void } -> untyped
|
12
|
+
def success: (*Symbol) { (untyped, Symbol) -> void } -> untyped
|
13
|
+
def unknown: () { (untyped, Symbol) -> void } -> untyped
|
14
|
+
|
15
|
+
alias type []
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader result: BCDD::Result
|
20
|
+
attr_reader allowed_types: BCDD::Result::Handler::AllowedTypes
|
21
|
+
|
22
|
+
def outcome?: -> bool
|
23
|
+
def outcome=: (Proc) -> void
|
24
|
+
def outcome: -> untyped
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class BCDD::Result::Handler
|
29
|
+
class AllowedTypes
|
30
|
+
attr_reader unchecked: Set[Symbol]
|
31
|
+
attr_reader type_checker: BCDD::Result::Contract::TypeChecker
|
32
|
+
|
33
|
+
def initialize: (
|
34
|
+
BCDD::Result::Contract::TypeChecker
|
35
|
+
) -> void
|
36
|
+
|
37
|
+
def allow?: (Array[Symbol]) -> bool
|
38
|
+
def allow_success?: (Array[Symbol]) -> bool
|
39
|
+
def allow_failure?: (Array[Symbol]) -> bool
|
40
|
+
|
41
|
+
def all_checked?: -> bool
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def check!: (Array[Symbol], bool) -> bool
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class BCDD::Result
|
2
|
+
module Mixin
|
3
|
+
module Factory
|
4
|
+
def self.module!: -> Module
|
5
|
+
end
|
6
|
+
|
7
|
+
module Methods
|
8
|
+
def Success: (Symbol type, ?untyped value) -> BCDD::Result::Success
|
9
|
+
|
10
|
+
def Failure: (Symbol type, ?untyped value) -> BCDD::Result::Failure
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def _ResultAs: (singleton(BCDD::Result), Symbol, untyped, ?terminal: bool) -> untyped
|
15
|
+
end
|
16
|
+
|
17
|
+
module Addons
|
18
|
+
module Continue
|
19
|
+
include BCDD::Result::Mixin::Methods
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def Continue: (untyped) -> BCDD::Result::Success
|
24
|
+
end
|
25
|
+
|
26
|
+
module Given
|
27
|
+
include BCDD::Result::Mixin::Methods
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def Given: (untyped) -> BCDD::Result::Success
|
32
|
+
end
|
33
|
+
|
34
|
+
OPTIONS: Hash[Symbol, Module]
|
35
|
+
|
36
|
+
def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.mixin: (?config: Hash[Symbol, Hash[Symbol, bool]]) -> Module
|
41
|
+
|
42
|
+
def self.mixin_module: -> singleton(BCDD::Result::Mixin)
|
43
|
+
|
44
|
+
def self.result_factory: -> singleton(BCDD::Result)
|
45
|
+
end
|