dry-validation 0.6.0 → 0.7.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/.codeclimate.yml +1 -0
- data/.travis.yml +3 -2
- data/CHANGELOG.md +42 -0
- data/Gemfile +8 -1
- data/README.md +13 -89
- data/config/errors.yml +35 -29
- data/dry-validation.gemspec +2 -2
- data/examples/basic.rb +3 -7
- data/examples/each.rb +3 -8
- data/examples/form.rb +3 -6
- data/examples/nested.rb +7 -15
- data/lib/dry/validation.rb +33 -5
- data/lib/dry/validation/error.rb +10 -26
- data/lib/dry/validation/error_compiler.rb +69 -99
- data/lib/dry/validation/error_compiler/input.rb +148 -0
- data/lib/dry/validation/hint_compiler.rb +83 -33
- data/lib/dry/validation/input_processor_compiler.rb +98 -0
- data/lib/dry/validation/input_processor_compiler/form.rb +46 -0
- data/lib/dry/validation/input_processor_compiler/sanitizer.rb +46 -0
- data/lib/dry/validation/messages/abstract.rb +30 -10
- data/lib/dry/validation/messages/i18n.rb +2 -1
- data/lib/dry/validation/messages/namespaced.rb +1 -0
- data/lib/dry/validation/messages/yaml.rb +8 -5
- data/lib/dry/validation/result.rb +33 -25
- data/lib/dry/validation/schema.rb +168 -61
- data/lib/dry/validation/schema/attr.rb +5 -27
- data/lib/dry/validation/schema/check.rb +24 -0
- data/lib/dry/validation/schema/dsl.rb +97 -0
- data/lib/dry/validation/schema/form.rb +2 -26
- data/lib/dry/validation/schema/key.rb +32 -28
- data/lib/dry/validation/schema/rule.rb +88 -32
- data/lib/dry/validation/schema/value.rb +77 -27
- data/lib/dry/validation/schema_compiler.rb +38 -0
- data/lib/dry/validation/version.rb +1 -1
- data/spec/fixtures/locales/pl.yml +1 -1
- data/spec/integration/attr_spec.rb +122 -0
- data/spec/integration/custom_error_messages_spec.rb +9 -11
- data/spec/integration/custom_predicates_spec.rb +68 -18
- data/spec/integration/error_compiler_spec.rb +259 -65
- data/spec/integration/hints_spec.rb +28 -9
- data/spec/integration/injecting_rules_spec.rb +11 -12
- data/spec/integration/localized_error_messages_spec.rb +16 -16
- data/spec/integration/messages/i18n_spec.rb +9 -5
- data/spec/integration/optional_keys_spec.rb +9 -11
- data/spec/integration/schema/array_schema_spec.rb +23 -0
- data/spec/integration/schema/check_rules_spec.rb +39 -31
- data/spec/integration/schema/check_with_nth_el_spec.rb +25 -0
- data/spec/integration/schema/each_with_set_spec.rb +23 -24
- data/spec/integration/schema/form_spec.rb +122 -0
- data/spec/integration/schema/inheriting_schema_spec.rb +31 -0
- data/spec/integration/schema/input_processor_spec.rb +46 -0
- data/spec/integration/schema/macros/confirmation_spec.rb +33 -0
- data/spec/integration/schema/macros/maybe_spec.rb +32 -0
- data/spec/integration/schema/macros/required_spec.rb +59 -0
- data/spec/integration/schema/macros/when_spec.rb +65 -0
- data/spec/integration/schema/nested_values_spec.rb +41 -0
- data/spec/integration/schema/not_spec.rb +14 -14
- data/spec/integration/schema/option_with_default_spec.rb +30 -0
- data/spec/integration/schema/reusing_schema_spec.rb +33 -0
- data/spec/integration/schema/using_types_spec.rb +29 -0
- data/spec/integration/schema/xor_spec.rb +17 -14
- data/spec/integration/schema_spec.rb +75 -245
- data/spec/shared/rule_compiler.rb +8 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/unit/hint_compiler_spec.rb +10 -10
- data/spec/unit/{input_type_compiler_spec.rb → input_processor_compiler/form_spec.rb} +88 -73
- data/spec/unit/schema/key_spec.rb +33 -0
- data/spec/unit/schema/rule_spec.rb +7 -6
- data/spec/unit/schema/value_spec.rb +187 -54
- metadata +53 -31
- data/.rubocop.yml +0 -16
- data/.rubocop_todo.yml +0 -7
- data/lib/dry/validation/input_type_compiler.rb +0 -83
- data/lib/dry/validation/schema/definition.rb +0 -74
- data/lib/dry/validation/schema/result.rb +0 -68
- data/rakelib/rubocop.rake +0 -18
- data/spec/integration/rule_groups_spec.rb +0 -94
- data/spec/integration/schema/attrs_spec.rb +0 -38
- data/spec/integration/schema/default_key_behavior_spec.rb +0 -23
- data/spec/integration/schema/grouped_rules_spec.rb +0 -57
- data/spec/integration/schema/nested_spec.rb +0 -31
- data/spec/integration/schema_form_spec.rb +0 -97
data/lib/dry/validation/error.rb
CHANGED
@@ -1,39 +1,23 @@
|
|
1
1
|
module Dry
|
2
2
|
module Validation
|
3
3
|
class Error
|
4
|
-
|
5
|
-
include Enumerable
|
4
|
+
include Dry::Equalizer(:name, :result)
|
6
5
|
|
7
|
-
|
6
|
+
attr_reader :name, :result
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def each(&block)
|
14
|
-
errors.each(&block)
|
15
|
-
end
|
16
|
-
|
17
|
-
def empty?
|
18
|
-
errors.empty?
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_ary
|
22
|
-
errors.map { |error| error.to_ary }
|
23
|
-
end
|
24
|
-
alias_method :to_a, :to_ary
|
8
|
+
def initialize(name, result)
|
9
|
+
@name = name
|
10
|
+
@result = result
|
25
11
|
end
|
26
12
|
|
27
|
-
|
28
|
-
|
29
|
-
def initialize(result)
|
30
|
-
@result = result
|
13
|
+
def schema?
|
14
|
+
result.response.is_a?(Validation::Result)
|
31
15
|
end
|
32
16
|
|
33
|
-
def
|
34
|
-
[:error, result.
|
17
|
+
def to_ast
|
18
|
+
node = [:error, [name, result.to_ast]]
|
19
|
+
schema? ? [:schema, node] : node
|
35
20
|
end
|
36
|
-
alias_method :to_a, :to_ary
|
37
21
|
end
|
38
22
|
end
|
39
23
|
end
|
@@ -1,18 +1,25 @@
|
|
1
1
|
module Dry
|
2
2
|
module Validation
|
3
3
|
class ErrorCompiler
|
4
|
-
attr_reader :messages, :options
|
4
|
+
attr_reader :messages, :hints, :options
|
5
5
|
|
6
6
|
DEFAULT_RESULT = {}.freeze
|
7
|
+
EMPTY_HINTS = [].freeze
|
7
8
|
KEY_SEPARATOR = '.'.freeze
|
8
9
|
|
9
10
|
def initialize(messages, options = {})
|
10
11
|
@messages = messages
|
11
|
-
@options = options
|
12
|
+
@options = Hash[options]
|
13
|
+
@hints = @options.fetch(:hints, {})
|
14
|
+
@full = options.fetch(:full, false)
|
12
15
|
end
|
13
16
|
|
14
|
-
def
|
15
|
-
|
17
|
+
def full?
|
18
|
+
@full
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(ast, *args)
|
22
|
+
merge(ast.map { |node| visit(node, *args) }) || DEFAULT_RESULT
|
16
23
|
end
|
17
24
|
|
18
25
|
def with(new_options)
|
@@ -23,135 +30,98 @@ module Dry
|
|
23
30
|
__send__(:"visit_#{node[0]}", node[1], *args)
|
24
31
|
end
|
25
32
|
|
26
|
-
def
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
def visit_input(input, *)
|
31
|
-
name = normalize_name(input[0])
|
32
|
-
_, value, rules = input
|
33
|
-
errors = [rules.map { |rule| visit(rule, name, value) }, value]
|
34
|
-
|
35
|
-
if input[0].is_a?(Hash)
|
36
|
-
root, sub = input[0].to_a.flatten
|
37
|
-
{ root => { sub => errors } }
|
38
|
-
else
|
39
|
-
{ input[0] => errors }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def visit_group(_, name, _)
|
44
|
-
messages[name, rule: name]
|
45
|
-
end
|
46
|
-
|
47
|
-
def visit_check(node, *)
|
48
|
-
name = normalize_name(node[0])
|
49
|
-
messages[name, rule: name]
|
50
|
-
end
|
51
|
-
|
52
|
-
def visit_key(rule, name, value)
|
53
|
-
_, predicate = rule
|
54
|
-
visit(predicate, value, name)
|
55
|
-
end
|
56
|
-
|
57
|
-
def visit_attr(rule, name, value)
|
58
|
-
_, predicate = rule
|
59
|
-
visit(predicate, value, name)
|
60
|
-
end
|
61
|
-
|
62
|
-
def visit_val(rule, name, value)
|
63
|
-
name, predicate = rule
|
64
|
-
visit(predicate, value, name)
|
65
|
-
end
|
66
|
-
|
67
|
-
def visit_predicate(predicate, value, name)
|
68
|
-
predicate_name, args = predicate
|
69
|
-
|
70
|
-
lookup_options = options.merge(
|
71
|
-
rule: name, val_type: value.class, arg_type: args[0].class
|
72
|
-
)
|
73
|
-
|
74
|
-
template = messages[predicate_name, lookup_options]
|
75
|
-
tokens = visit(predicate, value).merge(name: name)
|
76
|
-
|
77
|
-
template % tokens
|
33
|
+
def visit_schema(node, *args)
|
34
|
+
visit_error(node[1], true)
|
78
35
|
end
|
79
36
|
|
80
|
-
def
|
81
|
-
|
37
|
+
def visit_set(node, *args)
|
38
|
+
call(node, *args)
|
82
39
|
end
|
83
40
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
def visit_exclusion?(*args, _value)
|
89
|
-
{ list: args[0][0].join(', ') }
|
90
|
-
end
|
41
|
+
def visit_error(error, schema = false)
|
42
|
+
name, other = error
|
43
|
+
message = messages[name]
|
91
44
|
|
92
|
-
|
93
|
-
|
94
|
-
|
45
|
+
if message
|
46
|
+
{ name => [message] }
|
47
|
+
else
|
48
|
+
result = schema ? visit(other, name) : visit(other)
|
95
49
|
|
96
|
-
|
97
|
-
|
50
|
+
if result.is_a?(Array)
|
51
|
+
merge(result)
|
52
|
+
else
|
53
|
+
merge_hints(result)
|
54
|
+
end
|
55
|
+
end
|
98
56
|
end
|
99
57
|
|
100
|
-
def
|
101
|
-
|
58
|
+
def visit_input(node, path = nil)
|
59
|
+
name, result = node
|
60
|
+
visit(result, path || name)
|
102
61
|
end
|
103
62
|
|
104
|
-
def
|
105
|
-
|
63
|
+
def visit_result(node, name = nil)
|
64
|
+
value, other = node
|
65
|
+
input_visitor(name, value).visit(other)
|
106
66
|
end
|
107
67
|
|
108
|
-
def
|
109
|
-
|
68
|
+
def visit_implication(node)
|
69
|
+
_, right = node
|
70
|
+
visit(right)
|
110
71
|
end
|
111
72
|
|
112
|
-
def
|
113
|
-
|
73
|
+
def visit_key(rule)
|
74
|
+
_, predicate = rule
|
75
|
+
visit(predicate)
|
114
76
|
end
|
115
77
|
|
116
|
-
def
|
117
|
-
|
78
|
+
def visit_attr(rule)
|
79
|
+
_, predicate = rule
|
80
|
+
visit(predicate)
|
118
81
|
end
|
119
82
|
|
120
|
-
def
|
121
|
-
|
83
|
+
def visit_val(node)
|
84
|
+
visit(node)
|
122
85
|
end
|
123
86
|
|
124
|
-
|
125
|
-
{ eql_value: args[0][0], value: value }
|
126
|
-
end
|
87
|
+
private
|
127
88
|
|
128
|
-
def
|
129
|
-
|
89
|
+
def merge_hints(messages)
|
90
|
+
messages.each_with_object({}) do |(name, msgs), res|
|
91
|
+
if msgs.is_a?(Hash)
|
92
|
+
res[name] = merge_hints(msgs)
|
93
|
+
else
|
94
|
+
all_msgs = msgs + (hints[name] || EMPTY_HINTS)
|
95
|
+
all_msgs.uniq!
|
130
96
|
|
131
|
-
|
132
|
-
|
133
|
-
else
|
134
|
-
{ num: args[0][0], value: value }
|
97
|
+
res[name] = all_msgs
|
98
|
+
end
|
135
99
|
end
|
136
100
|
end
|
137
101
|
|
138
|
-
private
|
139
|
-
|
140
102
|
def normalize_name(name)
|
141
|
-
Array(name).join(
|
103
|
+
Array(name).join('.').to_sym
|
142
104
|
end
|
143
105
|
|
144
106
|
def merge(result)
|
145
|
-
result.reduce
|
146
|
-
|
147
|
-
|
107
|
+
result.reduce { |a, e| deep_merge(a, e) } || DEFAULT_RESULT
|
108
|
+
end
|
109
|
+
|
110
|
+
def deep_merge(left, right)
|
111
|
+
left.merge(right) do |_, a, e|
|
112
|
+
if a.is_a?(Hash)
|
113
|
+
deep_merge(a, e)
|
114
|
+
else
|
115
|
+
a + e
|
148
116
|
end
|
149
117
|
end
|
150
118
|
end
|
151
119
|
|
152
|
-
def
|
153
|
-
|
120
|
+
def input_visitor(name, input)
|
121
|
+
Input.new(messages, options.merge(name: name, input: input))
|
154
122
|
end
|
155
123
|
end
|
156
124
|
end
|
157
125
|
end
|
126
|
+
|
127
|
+
require 'dry/validation/error_compiler/input'
|
@@ -0,0 +1,148 @@
|
|
1
|
+
module Dry
|
2
|
+
module Validation
|
3
|
+
class ErrorCompiler::Input < ErrorCompiler
|
4
|
+
attr_reader :name, :input, :rule, :val_type
|
5
|
+
|
6
|
+
def initialize(messages, options)
|
7
|
+
super
|
8
|
+
@name = options.fetch(:name)
|
9
|
+
@input = options.fetch(:input)
|
10
|
+
@rule = Array(name).last
|
11
|
+
@val_type = input.class
|
12
|
+
end
|
13
|
+
|
14
|
+
def visit_each(node)
|
15
|
+
node.map { |el| visit(el) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def visit_set(node)
|
19
|
+
result = node.map do |input|
|
20
|
+
visit(input)
|
21
|
+
end
|
22
|
+
merge(result)
|
23
|
+
end
|
24
|
+
|
25
|
+
def visit_el(node)
|
26
|
+
idx, el = node
|
27
|
+
name = [*Array(name), idx]
|
28
|
+
visit(el, name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def visit_check(node)
|
32
|
+
_, other = node
|
33
|
+
visit(other)
|
34
|
+
end
|
35
|
+
|
36
|
+
def visit_predicate(node)
|
37
|
+
predicate, args = node
|
38
|
+
|
39
|
+
lookup_options = options.merge(
|
40
|
+
rule: rule, val_type: val_type, arg_type: args[0].class
|
41
|
+
)
|
42
|
+
|
43
|
+
tokens = options_for(predicate, args)
|
44
|
+
template = messages[predicate, lookup_options.merge(tokens)]
|
45
|
+
|
46
|
+
unless template
|
47
|
+
raise MissingMessageError.new("message for #{predicate} was not found")
|
48
|
+
end
|
49
|
+
|
50
|
+
rule_name =
|
51
|
+
if rule.is_a?(Symbol)
|
52
|
+
messages.rule(rule, lookup_options) || rule
|
53
|
+
else
|
54
|
+
rule
|
55
|
+
end
|
56
|
+
|
57
|
+
message =
|
58
|
+
if full?
|
59
|
+
"#{rule_name} #{template % tokens}"
|
60
|
+
else
|
61
|
+
template % tokens
|
62
|
+
end
|
63
|
+
|
64
|
+
path = [[message], *[tokens[:name], *Array(name).reverse].uniq]
|
65
|
+
|
66
|
+
path.reduce { |a, e| { e => a } }
|
67
|
+
end
|
68
|
+
|
69
|
+
def options_for_type?(*args)
|
70
|
+
{ type: args[0][0] }
|
71
|
+
end
|
72
|
+
|
73
|
+
def options_for_key?(*args)
|
74
|
+
{ name: args[0][0] }
|
75
|
+
end
|
76
|
+
|
77
|
+
def options_for_attr?(*args)
|
78
|
+
{ name: args[0][0] }
|
79
|
+
end
|
80
|
+
|
81
|
+
def options_for_exclusion?(*args)
|
82
|
+
{ list: args[0][0].join(', ') }
|
83
|
+
end
|
84
|
+
|
85
|
+
def options_for_inclusion?(*args)
|
86
|
+
{ list: args[0][0].join(', ') }
|
87
|
+
end
|
88
|
+
|
89
|
+
def options_for_gt?(*args)
|
90
|
+
{ num: args[0][0], value: input }
|
91
|
+
end
|
92
|
+
|
93
|
+
def options_for_gteq?(*args)
|
94
|
+
{ num: args[0][0], value: input }
|
95
|
+
end
|
96
|
+
|
97
|
+
def options_for_lt?(*args)
|
98
|
+
{ num: args[0][0], value: input }
|
99
|
+
end
|
100
|
+
|
101
|
+
def options_for_lteq?(*args)
|
102
|
+
{ num: args[0][0], value: input }
|
103
|
+
end
|
104
|
+
|
105
|
+
def options_for_int?(*args)
|
106
|
+
{ num: args[0][0], value: input }
|
107
|
+
end
|
108
|
+
|
109
|
+
def options_for_max_size?(*args)
|
110
|
+
{ num: args[0][0], value: input }
|
111
|
+
end
|
112
|
+
|
113
|
+
def options_for_min_size?(*args)
|
114
|
+
{ num: args[0][0], value: input }
|
115
|
+
end
|
116
|
+
|
117
|
+
def options_for_eql?(*args)
|
118
|
+
{ eql_value: args[0][0], value: input }
|
119
|
+
end
|
120
|
+
|
121
|
+
def options_for_size?(*args)
|
122
|
+
num = args[0][0]
|
123
|
+
|
124
|
+
if num.is_a?(Range)
|
125
|
+
{ left: num.first, right: num.last, value: input }
|
126
|
+
else
|
127
|
+
{ num: args[0][0], value: input }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def options_for(predicate, args)
|
132
|
+
meth = :"options_for_#{predicate}"
|
133
|
+
|
134
|
+
defaults = { name: rule, rule: rule, value: input }
|
135
|
+
|
136
|
+
if respond_to?(meth)
|
137
|
+
defaults.merge!(__send__(meth, args))
|
138
|
+
end
|
139
|
+
|
140
|
+
defaults
|
141
|
+
end
|
142
|
+
|
143
|
+
def input_visitor(new_name, value)
|
144
|
+
self.class.new(messages, options.merge(name: [*name, *new_name].uniq, input: value))
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -1,14 +1,37 @@
|
|
1
|
-
require 'dry/validation/error_compiler'
|
1
|
+
require 'dry/validation/error_compiler/input'
|
2
2
|
|
3
3
|
module Dry
|
4
4
|
module Validation
|
5
|
-
class HintCompiler < ErrorCompiler
|
6
|
-
|
5
|
+
class HintCompiler < ErrorCompiler::Input
|
6
|
+
include Dry::Equalizer(:messages, :rules, :options)
|
7
|
+
|
8
|
+
attr_reader :rules, :excluded
|
9
|
+
|
10
|
+
TYPES = {
|
11
|
+
none?: NilClass,
|
12
|
+
bool?: TrueClass,
|
13
|
+
str?: String,
|
14
|
+
int?: Fixnum,
|
15
|
+
float?: Float,
|
16
|
+
decimal?: BigDecimal,
|
17
|
+
date?: Date,
|
18
|
+
date_time?: DateTime,
|
19
|
+
time?: Time,
|
20
|
+
hash?: Hash,
|
21
|
+
array?: Array
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
EXCLUDED = [:none?, :filled?, :key?].freeze
|
25
|
+
|
26
|
+
def self.cache
|
27
|
+
@cache ||= ThreadSafe::Cache.new
|
28
|
+
end
|
7
29
|
|
8
30
|
def initialize(messages, options = {})
|
9
|
-
|
10
|
-
@options = Hash[options]
|
31
|
+
super(messages, { name: nil, input: nil }.merge(options))
|
11
32
|
@rules = @options.delete(:rules)
|
33
|
+
@excluded = @options.fetch(:excluded, EXCLUDED)
|
34
|
+
@val_type = options[:val_type]
|
12
35
|
end
|
13
36
|
|
14
37
|
def with(new_options)
|
@@ -16,58 +39,85 @@ module Dry
|
|
16
39
|
end
|
17
40
|
|
18
41
|
def call
|
19
|
-
|
42
|
+
self.class.cache.fetch_or_store(hash) do
|
43
|
+
super(rules)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def visit_predicate(node)
|
48
|
+
predicate, _ = node
|
49
|
+
|
50
|
+
val_type = TYPES[predicate]
|
51
|
+
|
52
|
+
return with(val_type: val_type) if val_type
|
53
|
+
return {} if excluded.include?(predicate)
|
20
54
|
|
21
|
-
|
22
|
-
|
23
|
-
|
55
|
+
super
|
56
|
+
end
|
57
|
+
|
58
|
+
def visit_set(node)
|
59
|
+
result = node.map do |el|
|
60
|
+
visit(el)
|
24
61
|
end
|
62
|
+
merge(result)
|
63
|
+
end
|
25
64
|
|
26
|
-
|
65
|
+
def visit_each(node)
|
66
|
+
visit(node)
|
27
67
|
end
|
28
68
|
|
29
69
|
def visit_or(node)
|
30
70
|
left, right = node
|
31
|
-
[visit(left),
|
71
|
+
merge([visit(left), visit(right)])
|
32
72
|
end
|
33
73
|
|
34
74
|
def visit_and(node)
|
35
75
|
left, right = node
|
36
|
-
[visit(left), Array(visit(right)).flatten.compact].compact
|
37
|
-
end
|
38
76
|
|
39
|
-
|
40
|
-
name, predicate = node
|
41
|
-
visit(predicate, name)
|
42
|
-
end
|
77
|
+
result = visit(left)
|
43
78
|
|
44
|
-
|
45
|
-
|
79
|
+
if result.is_a?(self.class)
|
80
|
+
result.visit(right)
|
81
|
+
else
|
82
|
+
visit(right)
|
83
|
+
end
|
84
|
+
end
|
46
85
|
|
47
|
-
|
86
|
+
def visit_implication(node)
|
87
|
+
_, right = node
|
88
|
+
visit(right)
|
89
|
+
end
|
48
90
|
|
49
|
-
|
50
|
-
|
91
|
+
def visit_key(node)
|
92
|
+
name, predicate = node
|
93
|
+
with(name: Array([*self.name, name])).visit(predicate)
|
94
|
+
end
|
95
|
+
alias_method :visit_attr, :visit_key
|
51
96
|
|
52
|
-
|
97
|
+
def visit_val(node)
|
98
|
+
visit(node)
|
99
|
+
end
|
53
100
|
|
54
|
-
|
101
|
+
def visit_schema(node)
|
102
|
+
DEFAULT_RESULT
|
103
|
+
end
|
55
104
|
|
56
|
-
|
105
|
+
def visit_check(node)
|
106
|
+
DEFAULT_RESULT
|
57
107
|
end
|
58
108
|
|
59
|
-
def
|
60
|
-
|
61
|
-
name
|
109
|
+
def visit_xor(node)
|
110
|
+
DEFAULT_RESULT
|
62
111
|
end
|
63
112
|
|
64
|
-
def
|
65
|
-
|
66
|
-
name
|
113
|
+
def visit_not(node)
|
114
|
+
DEFAULT_RESULT
|
67
115
|
end
|
68
116
|
|
69
|
-
|
70
|
-
|
117
|
+
private
|
118
|
+
|
119
|
+
def merge(result)
|
120
|
+
super(result.reject { |el| el.is_a?(self.class) })
|
71
121
|
end
|
72
122
|
end
|
73
123
|
end
|