bcdd-result 0.4.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +28 -0
- data/.rubocop_todo.yml +3 -13
- data/CHANGELOG.md +95 -2
- data/README.md +572 -18
- data/lib/bcdd/result/data.rb +12 -7
- data/lib/bcdd/result/error.rb +9 -1
- data/lib/bcdd/result/expectations/contract/disabled.rb +25 -0
- data/lib/bcdd/result/expectations/contract/evaluator.rb +45 -0
- data/lib/bcdd/result/expectations/contract/for_types.rb +29 -0
- data/lib/bcdd/result/expectations/contract/for_types_and_values.rb +37 -0
- data/lib/bcdd/result/expectations/contract/interface.rb +21 -0
- data/lib/bcdd/result/expectations/contract.rb +25 -0
- data/lib/bcdd/result/expectations/error.rb +15 -0
- data/lib/bcdd/result/expectations/mixin.rb +37 -0
- data/lib/bcdd/result/expectations/type_checker.rb +33 -0
- data/lib/bcdd/result/expectations.rb +50 -0
- data/lib/bcdd/result/failure.rb +1 -1
- data/lib/bcdd/result/handler/allowed_types.rb +45 -0
- data/lib/bcdd/result/handler.rb +13 -8
- data/lib/bcdd/result/mixin.rb +31 -4
- data/lib/bcdd/result/success.rb +1 -1
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +24 -19
- data/sig/bcdd/result.rbs +229 -40
- metadata +13 -3
- data/lib/bcdd/result/type.rb +0 -17
data/lib/bcdd/result/error.rb
CHANGED
@@ -38,7 +38,15 @@ class BCDD::Result::Error < StandardError
|
|
38
38
|
|
39
39
|
class WrongSubjectMethodArity < self
|
40
40
|
def self.build(subject:, method:)
|
41
|
-
new("#{subject.class}##{method.name} has unsupported arity (#{method.arity}). Expected 0 or
|
41
|
+
new("#{subject.class}##{method.name} has unsupported arity (#{method.arity}). Expected 0, 1 or 2.")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class UnhandledTypes < self
|
46
|
+
def self.build(types:)
|
47
|
+
subject = types.size == 1 ? 'This was' : 'These were'
|
48
|
+
|
49
|
+
new("You must handle all cases. #{subject} not handled: #{types.map(&:inspect).join(', ')}")
|
42
50
|
end
|
43
51
|
end
|
44
52
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations
|
4
|
+
module Contract::Disabled
|
5
|
+
extend Contract::Interface
|
6
|
+
|
7
|
+
EMPTY_SET = Set.new.freeze
|
8
|
+
|
9
|
+
def self.allowed_types
|
10
|
+
EMPTY_SET
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.type?(_type)
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.type!(type)
|
18
|
+
type
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.type_and_value!(_data); end
|
22
|
+
|
23
|
+
private_constant :EMPTY_SET
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations
|
4
|
+
class Contract::Evaluator
|
5
|
+
include Contract::Interface
|
6
|
+
|
7
|
+
attr_reader :allowed_types, :success, :failure
|
8
|
+
|
9
|
+
def initialize(success, failure)
|
10
|
+
@success = success
|
11
|
+
@failure = failure
|
12
|
+
|
13
|
+
@allowed_types = (success.allowed_types | failure.allowed_types).freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
def type?(type)
|
17
|
+
success_disabled = success == Contract::Disabled
|
18
|
+
failure_disabled = failure == Contract::Disabled
|
19
|
+
|
20
|
+
return Contract::Disabled.type?(type) if success_disabled && failure_disabled
|
21
|
+
|
22
|
+
(!success_disabled && success.type?(type)) || (!failure_disabled && failure.type?(type))
|
23
|
+
end
|
24
|
+
|
25
|
+
def type!(type)
|
26
|
+
return type if type?(type)
|
27
|
+
|
28
|
+
raise Error::UnexpectedType.build(type: type, allowed_types: allowed_types)
|
29
|
+
end
|
30
|
+
|
31
|
+
def type_and_value!(data)
|
32
|
+
self.for(data).type_and_value!(data)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def for(data)
|
38
|
+
case data.name
|
39
|
+
when :unknown then Contract::Disabled
|
40
|
+
when :success then success
|
41
|
+
else failure
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations
|
4
|
+
class Contract::ForTypes
|
5
|
+
include Contract::Interface
|
6
|
+
|
7
|
+
attr_reader :allowed_types
|
8
|
+
|
9
|
+
def initialize(types)
|
10
|
+
@allowed_types = Array(types).map(&:to_sym).to_set.freeze
|
11
|
+
end
|
12
|
+
|
13
|
+
def type?(type)
|
14
|
+
allowed_types.member?(type)
|
15
|
+
end
|
16
|
+
|
17
|
+
def type!(type)
|
18
|
+
return type if type?(type)
|
19
|
+
|
20
|
+
raise Error::UnexpectedType.build(type: type, allowed_types: allowed_types)
|
21
|
+
end
|
22
|
+
|
23
|
+
def type_and_value!(data)
|
24
|
+
type!(data.type)
|
25
|
+
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations
|
4
|
+
class Contract::ForTypesAndValues
|
5
|
+
include Contract::Interface
|
6
|
+
|
7
|
+
def initialize(types_and_values)
|
8
|
+
@types_and_values = types_and_values.transform_keys(&:to_sym)
|
9
|
+
|
10
|
+
@types_contract = Contract::ForTypes.new(@types_and_values.keys)
|
11
|
+
end
|
12
|
+
|
13
|
+
def allowed_types
|
14
|
+
@types_contract.allowed_types
|
15
|
+
end
|
16
|
+
|
17
|
+
def type?(type)
|
18
|
+
@types_contract.type?(type)
|
19
|
+
end
|
20
|
+
|
21
|
+
def type!(type)
|
22
|
+
@types_contract.type!(type)
|
23
|
+
end
|
24
|
+
|
25
|
+
def type_and_value!(data)
|
26
|
+
type = data.type
|
27
|
+
value = data.value
|
28
|
+
allowed_value = @types_and_values[type!(type)]
|
29
|
+
|
30
|
+
return value if allowed_value === value
|
31
|
+
|
32
|
+
raise Error::UnexpectedValue.build(type: type, value: value)
|
33
|
+
rescue NoMatchingPatternError
|
34
|
+
raise Error::UnexpectedValue.build(type: data.type, value: data.value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations
|
4
|
+
module Contract::Interface
|
5
|
+
def allowed_types
|
6
|
+
raise ::BCDD::Result::Error::NotImplemented
|
7
|
+
end
|
8
|
+
|
9
|
+
def type?(_type)
|
10
|
+
raise ::BCDD::Result::Error::NotImplemented
|
11
|
+
end
|
12
|
+
|
13
|
+
def type!(_type)
|
14
|
+
raise ::BCDD::Result::Error::NotImplemented
|
15
|
+
end
|
16
|
+
|
17
|
+
def type_and_value!(_data)
|
18
|
+
raise ::BCDD::Result::Error::NotImplemented
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations
|
4
|
+
module Contract
|
5
|
+
require_relative 'contract/interface'
|
6
|
+
require_relative 'contract/evaluator'
|
7
|
+
require_relative 'contract/disabled'
|
8
|
+
require_relative 'contract/for_types'
|
9
|
+
require_relative 'contract/for_types_and_values'
|
10
|
+
|
11
|
+
NONE = Contract::Evaluator.new(Contract::Disabled, Contract::Disabled).freeze
|
12
|
+
|
13
|
+
ToEnsure = ->(spec) do
|
14
|
+
return Contract::Disabled if spec.nil?
|
15
|
+
|
16
|
+
spec.is_a?(Hash) ? Contract::ForTypesAndValues.new(spec) : Contract::ForTypes.new(Array(spec))
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.new(success:, failure:)
|
20
|
+
Contract::Evaluator.new(ToEnsure[success], ToEnsure[failure])
|
21
|
+
end
|
22
|
+
|
23
|
+
private_constant :ToEnsure
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations::Error < BCDD::Result::Error
|
4
|
+
class UnexpectedType < self
|
5
|
+
def self.build(type:, allowed_types:)
|
6
|
+
new("type :#{type} is not allowed. Allowed types: #{allowed_types.map(&:inspect).join(', ')}")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class UnexpectedValue < self
|
11
|
+
def self.build(type:, value:)
|
12
|
+
new("value #{value.inspect} is not allowed for :#{type} type")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations
|
4
|
+
module Mixin
|
5
|
+
METHODS = <<~RUBY
|
6
|
+
def Success(...)
|
7
|
+
__expected::Success(...)
|
8
|
+
end
|
9
|
+
|
10
|
+
def Failure(...)
|
11
|
+
__expected::Failure(...)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def __expected
|
17
|
+
@__expected ||= Expected.with(subject: self)
|
18
|
+
end
|
19
|
+
RUBY
|
20
|
+
|
21
|
+
module Addons
|
22
|
+
module Continuable
|
23
|
+
private def Continue(value)
|
24
|
+
::BCDD::Result::Success.new(type: :continued, value: value, subject: self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
OPTIONS = { Continue: Continuable }.freeze
|
29
|
+
|
30
|
+
def self.options(names)
|
31
|
+
Array(names).filter_map { |name| OPTIONS[name] }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private_constant :Mixin
|
37
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations
|
4
|
+
class TypeChecker
|
5
|
+
attr_reader :result_type, :expectations
|
6
|
+
|
7
|
+
def initialize(result_type, expectations:)
|
8
|
+
@result_type = result_type
|
9
|
+
|
10
|
+
@expectations = expectations
|
11
|
+
end
|
12
|
+
|
13
|
+
def allow?(types)
|
14
|
+
validate(types, expected: expectations, allow_empty: false)
|
15
|
+
end
|
16
|
+
|
17
|
+
def allow_success?(types)
|
18
|
+
validate(types, expected: expectations.success, allow_empty: true)
|
19
|
+
end
|
20
|
+
|
21
|
+
def allow_failure?(types)
|
22
|
+
validate(types, expected: expectations.failure, allow_empty: true)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def validate(types, expected:, allow_empty:)
|
28
|
+
(allow_empty && types.empty?) || types.any? { |type| expected.type!(type) == result_type }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private_constant :TypeChecker
|
33
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Expectations
|
4
|
+
require_relative 'expectations/mixin'
|
5
|
+
require_relative 'expectations/error'
|
6
|
+
require_relative 'expectations/contract'
|
7
|
+
require_relative 'expectations/type_checker'
|
8
|
+
|
9
|
+
def self.mixin(success: nil, failure: nil, with: nil)
|
10
|
+
addons = Mixin::Addons.options(with)
|
11
|
+
|
12
|
+
mod = Module.new
|
13
|
+
mod.const_set(:Expected, new(success: success, failure: failure).freeze)
|
14
|
+
mod.module_eval(Mixin::METHODS)
|
15
|
+
mod.send(:include, *addons) unless addons.empty?
|
16
|
+
mod
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.evaluate(data, expectations)
|
20
|
+
expectations ||= Contract::NONE
|
21
|
+
|
22
|
+
expectations.type_and_value!(data)
|
23
|
+
|
24
|
+
TypeChecker.new(data.type, expectations: expectations)
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(subject: nil, success: nil, failure: nil, contract: nil)
|
28
|
+
@subject = subject
|
29
|
+
|
30
|
+
@contract = contract if contract.is_a?(Contract::Evaluator)
|
31
|
+
|
32
|
+
@contract ||= Contract.new(success: success, failure: failure).freeze
|
33
|
+
end
|
34
|
+
|
35
|
+
def Success(type, value = nil)
|
36
|
+
::BCDD::Result::Success.new(type: type, value: value, subject: subject, expectations: contract)
|
37
|
+
end
|
38
|
+
|
39
|
+
def Failure(type, value = nil)
|
40
|
+
::BCDD::Result::Failure.new(type: type, value: value, subject: subject, expectations: contract)
|
41
|
+
end
|
42
|
+
|
43
|
+
def with(subject:)
|
44
|
+
self.class.new(subject: subject, contract: contract)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
attr_reader :subject, :contract
|
50
|
+
end
|
data/lib/bcdd/result/failure.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
class Handler
|
5
|
+
class AllowedTypes
|
6
|
+
attr_reader :unchecked, :type_checker
|
7
|
+
|
8
|
+
def initialize(type_checker)
|
9
|
+
@type_checker = type_checker
|
10
|
+
|
11
|
+
@expectations = type_checker.expectations
|
12
|
+
|
13
|
+
@unchecked = @expectations.allowed_types.dup
|
14
|
+
end
|
15
|
+
|
16
|
+
def allow?(types)
|
17
|
+
check!(types, type_checker.allow?(types))
|
18
|
+
end
|
19
|
+
|
20
|
+
def allow_success?(types)
|
21
|
+
unchecked.subtract(@expectations.success.allowed_types) if types.empty?
|
22
|
+
|
23
|
+
check!(types, type_checker.allow_success?(types))
|
24
|
+
end
|
25
|
+
|
26
|
+
def allow_failure?(types)
|
27
|
+
unchecked.subtract(@expectations.failure.allowed_types) if types.empty?
|
28
|
+
|
29
|
+
check!(types, type_checker.allow_failure?(types))
|
30
|
+
end
|
31
|
+
|
32
|
+
def all_checked?
|
33
|
+
unchecked.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def check!(types, checked)
|
39
|
+
unchecked.subtract(types) unless all_checked?
|
40
|
+
|
41
|
+
checked
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/bcdd/result/handler.rb
CHANGED
@@ -2,27 +2,30 @@
|
|
2
2
|
|
3
3
|
class BCDD::Result
|
4
4
|
class Handler
|
5
|
+
require_relative 'handler/allowed_types'
|
6
|
+
|
5
7
|
UNDEFINED = ::Object.new
|
6
8
|
|
7
|
-
def initialize(result)
|
9
|
+
def initialize(result, type_checker:)
|
10
|
+
@allowed_types = AllowedTypes.new(type_checker)
|
11
|
+
|
8
12
|
@outcome = UNDEFINED
|
9
13
|
|
10
|
-
@_type = result._type
|
11
14
|
@result = result
|
12
15
|
end
|
13
16
|
|
14
17
|
def [](*types, &block)
|
15
18
|
raise Error::MissingTypeArgument if types.empty?
|
16
19
|
|
17
|
-
self.outcome = block if
|
20
|
+
self.outcome = block if allowed_types.allow?(types)
|
18
21
|
end
|
19
22
|
|
20
|
-
def
|
21
|
-
self.outcome = block if
|
23
|
+
def success(*types, &block)
|
24
|
+
self.outcome = block if allowed_types.allow_success?(types) && result.success?
|
22
25
|
end
|
23
26
|
|
24
|
-
def
|
25
|
-
self.outcome = block if
|
27
|
+
def failure(*types, &block)
|
28
|
+
self.outcome = block if allowed_types.allow_failure?(types) && result.failure?
|
26
29
|
end
|
27
30
|
|
28
31
|
def unknown(&block)
|
@@ -33,7 +36,7 @@ class BCDD::Result
|
|
33
36
|
|
34
37
|
private
|
35
38
|
|
36
|
-
attr_reader :
|
39
|
+
attr_reader :result, :allowed_types
|
37
40
|
|
38
41
|
def outcome?
|
39
42
|
@outcome != UNDEFINED
|
@@ -44,6 +47,8 @@ class BCDD::Result
|
|
44
47
|
end
|
45
48
|
|
46
49
|
def outcome
|
50
|
+
allowed_types.all_checked? or raise Error::UnhandledTypes.build(types: allowed_types.unchecked)
|
51
|
+
|
47
52
|
@outcome if outcome?
|
48
53
|
end
|
49
54
|
end
|
data/lib/bcdd/result/mixin.rb
CHANGED
@@ -2,12 +2,39 @@
|
|
2
2
|
|
3
3
|
class BCDD::Result
|
4
4
|
module Mixin
|
5
|
-
|
6
|
-
Success
|
5
|
+
module Methods
|
6
|
+
def Success(type, value = nil)
|
7
|
+
Success.new(type: type, value: value, subject: self)
|
8
|
+
end
|
9
|
+
|
10
|
+
def Failure(type, value = nil)
|
11
|
+
Failure.new(type: type, value: value, subject: self)
|
12
|
+
end
|
7
13
|
end
|
8
14
|
|
9
|
-
|
10
|
-
|
15
|
+
module Addons
|
16
|
+
module Continuable
|
17
|
+
private def Continue(value)
|
18
|
+
Success(:continued, value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
OPTIONS = { Continue: Continuable }.freeze
|
23
|
+
|
24
|
+
def self.options(names)
|
25
|
+
Array(names).filter_map { |name| OPTIONS[name] }
|
26
|
+
end
|
11
27
|
end
|
12
28
|
end
|
29
|
+
|
30
|
+
def self.mixin(with: nil)
|
31
|
+
addons = Mixin::Addons.options(with)
|
32
|
+
|
33
|
+
mod = Module.new
|
34
|
+
mod.send(:include, Mixin::Methods)
|
35
|
+
mod.send(:include, *addons) unless addons.empty?
|
36
|
+
mod
|
37
|
+
end
|
38
|
+
|
39
|
+
private_constant :Mixin
|
13
40
|
end
|
data/lib/bcdd/result/success.rb
CHANGED
data/lib/bcdd/result/version.rb
CHANGED
data/lib/bcdd/result.rb
CHANGED
@@ -2,32 +2,38 @@
|
|
2
2
|
|
3
3
|
require_relative 'result/version'
|
4
4
|
require_relative 'result/error'
|
5
|
-
require_relative 'result/type'
|
6
5
|
require_relative 'result/data'
|
7
6
|
require_relative 'result/handler'
|
8
7
|
require_relative 'result/failure'
|
9
8
|
require_relative 'result/success'
|
10
9
|
require_relative 'result/mixin'
|
10
|
+
require_relative 'result/expectations'
|
11
11
|
|
12
12
|
class BCDD::Result
|
13
13
|
attr_accessor :unknown
|
14
14
|
|
15
|
-
attr_reader :
|
15
|
+
attr_reader :subject, :data, :type_checker
|
16
16
|
|
17
17
|
protected :subject
|
18
18
|
|
19
|
-
private :unknown, :unknown
|
19
|
+
private :unknown, :unknown=, :type_checker
|
20
20
|
|
21
|
-
def initialize(type:, value:, subject: nil)
|
22
|
-
|
23
|
-
|
21
|
+
def initialize(type:, value:, subject: nil, expectations: nil)
|
22
|
+
data = Data.new(name, type, value)
|
23
|
+
|
24
|
+
@type_checker = Expectations.evaluate(data, expectations)
|
24
25
|
@subject = subject
|
26
|
+
@data = data
|
25
27
|
|
26
28
|
self.unknown = true
|
27
29
|
end
|
28
30
|
|
29
31
|
def type
|
30
|
-
|
32
|
+
data.type
|
33
|
+
end
|
34
|
+
|
35
|
+
def value
|
36
|
+
data.value
|
31
37
|
end
|
32
38
|
|
33
39
|
def success?(_type = nil)
|
@@ -45,25 +51,27 @@ class BCDD::Result
|
|
45
51
|
def on(*types, &block)
|
46
52
|
raise Error::MissingTypeArgument if types.empty?
|
47
53
|
|
48
|
-
tap { known(block) if
|
54
|
+
tap { known(block) if type_checker.allow?(types) }
|
49
55
|
end
|
50
56
|
|
51
57
|
def on_success(*types, &block)
|
52
|
-
tap { known(block) if
|
58
|
+
tap { known(block) if type_checker.allow_success?(types) && success? }
|
53
59
|
end
|
54
60
|
|
55
61
|
def on_failure(*types, &block)
|
56
|
-
tap { known(block) if
|
62
|
+
tap { known(block) if type_checker.allow_failure?(types) && failure? }
|
57
63
|
end
|
58
64
|
|
59
65
|
def on_unknown
|
60
66
|
tap { yield(value, type) if unknown }
|
61
67
|
end
|
62
68
|
|
63
|
-
def and_then(method_name = nil)
|
69
|
+
def and_then(method_name = nil, context = nil)
|
64
70
|
return self if failure?
|
65
71
|
|
66
|
-
|
72
|
+
method_name && block_given? and raise ArgumentError, 'method_name and block are mutually exclusive'
|
73
|
+
|
74
|
+
return call_subject_method(method_name, context) if method_name
|
67
75
|
|
68
76
|
result = yield(value)
|
69
77
|
|
@@ -71,17 +79,13 @@ class BCDD::Result
|
|
71
79
|
end
|
72
80
|
|
73
81
|
def handle
|
74
|
-
handler = Handler.new(self)
|
82
|
+
handler = Handler.new(self, type_checker: type_checker)
|
75
83
|
|
76
84
|
yield handler
|
77
85
|
|
78
86
|
handler.send(:outcome)
|
79
87
|
end
|
80
88
|
|
81
|
-
def data
|
82
|
-
Data.new(self)
|
83
|
-
end
|
84
|
-
|
85
89
|
def ==(other)
|
86
90
|
self.class == other.class && type == other.type && value == other.value
|
87
91
|
end
|
@@ -108,7 +112,7 @@ class BCDD::Result
|
|
108
112
|
private
|
109
113
|
|
110
114
|
def name
|
111
|
-
|
115
|
+
:unknown
|
112
116
|
end
|
113
117
|
|
114
118
|
def known(block)
|
@@ -117,13 +121,14 @@ class BCDD::Result
|
|
117
121
|
block.call(value, type)
|
118
122
|
end
|
119
123
|
|
120
|
-
def call_subject_method(method_name)
|
124
|
+
def call_subject_method(method_name, context)
|
121
125
|
method = subject.method(method_name)
|
122
126
|
|
123
127
|
result =
|
124
128
|
case method.arity
|
125
129
|
when 0 then subject.send(method_name)
|
126
130
|
when 1 then subject.send(method_name, value)
|
131
|
+
when 2 then subject.send(method_name, value, context)
|
127
132
|
else raise Error::WrongSubjectMethodArity.build(subject: subject, method: method)
|
128
133
|
end
|
129
134
|
|