hocon 0.0.7 → 0.1.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 +7 -0
- data/README.md +4 -2
- data/lib/hocon.rb +2 -0
- data/lib/hocon/config.rb +1010 -0
- data/lib/hocon/config_error.rb +32 -2
- data/lib/hocon/config_factory.rb +46 -0
- data/lib/hocon/config_include_context.rb +49 -0
- data/lib/hocon/config_includer_file.rb +27 -0
- data/lib/hocon/config_list.rb +49 -0
- data/lib/hocon/config_mergeable.rb +74 -0
- data/lib/hocon/config_object.rb +144 -1
- data/lib/hocon/config_parse_options.rb +33 -9
- data/lib/hocon/config_parseable.rb +51 -0
- data/lib/hocon/config_render_options.rb +4 -2
- data/lib/hocon/config_resolve_options.rb +31 -0
- data/lib/hocon/config_syntax.rb +5 -2
- data/lib/hocon/config_util.rb +73 -0
- data/lib/hocon/config_value.rb +122 -0
- data/lib/hocon/config_value_factory.rb +66 -2
- data/lib/hocon/config_value_type.rb +5 -2
- data/lib/hocon/impl.rb +2 -0
- data/lib/hocon/impl/abstract_config_node.rb +29 -0
- data/lib/hocon/impl/abstract_config_node_value.rb +11 -0
- data/lib/hocon/impl/abstract_config_object.rb +148 -42
- data/lib/hocon/impl/abstract_config_value.rb +251 -11
- data/lib/hocon/impl/array_iterator.rb +19 -0
- data/lib/hocon/impl/config_boolean.rb +7 -1
- data/lib/hocon/impl/config_concatenation.rb +177 -28
- data/lib/hocon/impl/config_delayed_merge.rb +329 -0
- data/lib/hocon/impl/config_delayed_merge_object.rb +274 -0
- data/lib/hocon/impl/config_document_parser.rb +647 -0
- data/lib/hocon/impl/config_double.rb +44 -0
- data/lib/hocon/impl/config_impl.rb +143 -19
- data/lib/hocon/impl/config_impl_util.rb +18 -0
- data/lib/hocon/impl/config_include_kind.rb +10 -0
- data/lib/hocon/impl/config_int.rb +13 -1
- data/lib/hocon/impl/config_node_array.rb +11 -0
- data/lib/hocon/impl/config_node_comment.rb +19 -0
- data/lib/hocon/impl/config_node_complex_value.rb +54 -0
- data/lib/hocon/impl/config_node_concatenation.rb +11 -0
- data/lib/hocon/impl/config_node_field.rb +81 -0
- data/lib/hocon/impl/config_node_include.rb +33 -0
- data/lib/hocon/impl/config_node_object.rb +276 -0
- data/lib/hocon/impl/config_node_path.rb +48 -0
- data/lib/hocon/impl/config_node_root.rb +60 -0
- data/lib/hocon/impl/config_node_simple_value.rb +42 -0
- data/lib/hocon/impl/config_node_single_token.rb +17 -0
- data/lib/hocon/impl/config_null.rb +15 -7
- data/lib/hocon/impl/config_number.rb +43 -4
- data/lib/hocon/impl/config_parser.rb +403 -0
- data/lib/hocon/impl/config_reference.rb +142 -0
- data/lib/hocon/impl/config_string.rb +55 -7
- data/lib/hocon/impl/container.rb +29 -0
- data/lib/hocon/impl/default_transformer.rb +24 -15
- data/lib/hocon/impl/from_map_mode.rb +3 -1
- data/lib/hocon/impl/full_includer.rb +2 -0
- data/lib/hocon/impl/memo_key.rb +42 -0
- data/lib/hocon/impl/mergeable_value.rb +8 -0
- data/lib/hocon/impl/origin_type.rb +8 -2
- data/lib/hocon/impl/parseable.rb +455 -91
- data/lib/hocon/impl/path.rb +181 -59
- data/lib/hocon/impl/path_builder.rb +24 -3
- data/lib/hocon/impl/path_parser.rb +280 -0
- data/lib/hocon/impl/replaceable_merge_stack.rb +22 -0
- data/lib/hocon/impl/resolve_context.rb +254 -0
- data/lib/hocon/impl/resolve_memos.rb +21 -0
- data/lib/hocon/impl/resolve_result.rb +39 -0
- data/lib/hocon/impl/resolve_source.rb +354 -0
- data/lib/hocon/impl/resolve_status.rb +3 -1
- data/lib/hocon/impl/simple_config.rb +264 -10
- data/lib/hocon/impl/simple_config_document.rb +48 -0
- data/lib/hocon/impl/simple_config_list.rb +282 -8
- data/lib/hocon/impl/simple_config_object.rb +424 -88
- data/lib/hocon/impl/simple_config_origin.rb +263 -71
- data/lib/hocon/impl/simple_include_context.rb +31 -1
- data/lib/hocon/impl/simple_includer.rb +196 -1
- data/lib/hocon/impl/substitution_expression.rb +38 -0
- data/lib/hocon/impl/token.rb +17 -4
- data/lib/hocon/impl/token_type.rb +6 -2
- data/lib/hocon/impl/tokenizer.rb +339 -109
- data/lib/hocon/impl/tokens.rb +330 -79
- data/lib/hocon/impl/unmergeable.rb +14 -1
- data/lib/hocon/impl/unsupported_operation_error.rb +6 -0
- data/lib/hocon/impl/url.rb +37 -0
- data/lib/hocon/parser.rb +7 -0
- data/lib/hocon/parser/config_document.rb +92 -0
- data/lib/hocon/parser/config_document_factory.rb +36 -0
- data/lib/hocon/parser/config_node.rb +30 -0
- metadata +67 -43
- data/lib/hocon/impl/config_float.rb +0 -13
- data/lib/hocon/impl/parser.rb +0 -977
- data/lib/hocon/impl/properties_parser.rb +0 -83
@@ -1,10 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'hocon/impl'
|
2
4
|
require 'hocon/config_value_type'
|
5
|
+
require 'hocon/config_resolve_options'
|
3
6
|
require 'hocon/impl/path'
|
4
7
|
require 'hocon/impl/default_transformer'
|
5
8
|
require 'hocon/impl/config_impl'
|
9
|
+
require 'hocon/impl/resolve_context'
|
10
|
+
require 'hocon/config_mergeable'
|
6
11
|
|
7
12
|
class Hocon::Impl::SimpleConfig
|
13
|
+
include Hocon::ConfigMergeable
|
8
14
|
|
9
15
|
ConfigMissingError = Hocon::ConfigError::ConfigMissingError
|
10
16
|
ConfigNotResolvedError = Hocon::ConfigError::ConfigNotResolvedError
|
@@ -14,15 +20,35 @@ class Hocon::Impl::SimpleConfig
|
|
14
20
|
Path = Hocon::Impl::Path
|
15
21
|
DefaultTransformer = Hocon::Impl::DefaultTransformer
|
16
22
|
|
23
|
+
attr_reader :object
|
24
|
+
|
17
25
|
def initialize(object)
|
18
26
|
@object = object
|
19
27
|
end
|
28
|
+
attr_reader :object
|
20
29
|
|
21
30
|
def root
|
22
31
|
@object
|
23
32
|
end
|
24
33
|
|
25
|
-
def
|
34
|
+
def origin
|
35
|
+
@object.origin
|
36
|
+
end
|
37
|
+
|
38
|
+
def resolve(options = Hocon::ConfigResolveOptions.defaults)
|
39
|
+
resolve_with(self, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def resolve_with(source, options)
|
43
|
+
resolved = Hocon::Impl::ResolveContext.resolve(@object, source.object, options)
|
44
|
+
if resolved.eql?(@object)
|
45
|
+
self
|
46
|
+
else
|
47
|
+
Hocon::Impl::SimpleConfig.new(resolved)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.find_key(me, key, expected, original_path)
|
26
52
|
v = me.peek_assuming_resolved(key, original_path)
|
27
53
|
if v.nil?
|
28
54
|
raise ConfigMissingError.new(nil, "No configuration setting found for key '#{original_path.render}'", nil)
|
@@ -35,12 +61,12 @@ class Hocon::Impl::SimpleConfig
|
|
35
61
|
if v.value_type == ConfigValueType::NULL
|
36
62
|
raise ConfigNullError.new(v.origin,
|
37
63
|
(ConfigNullError.make_message(original_path.render,
|
38
|
-
(not expected.nil?) ?
|
64
|
+
(not expected.nil?) ? ConfigValueType.name(expected) : nil)),
|
39
65
|
nil)
|
40
66
|
elsif (not expected.nil?) && v.value_type != expected
|
41
67
|
raise ConfigWrongTypeError.new(v.origin,
|
42
|
-
"#{original_path.render} has type #{v.value_type
|
43
|
-
"rather than #{
|
68
|
+
"#{original_path.render} has type #{ConfigValueType.name(v.value_type)} " +
|
69
|
+
"rather than #{ConfigValueType.name(expected)}",
|
44
70
|
nil)
|
45
71
|
else
|
46
72
|
return v
|
@@ -51,30 +77,250 @@ class Hocon::Impl::SimpleConfig
|
|
51
77
|
key = path.first
|
52
78
|
rest = path.remainder
|
53
79
|
if rest.nil?
|
54
|
-
find_key(me, key, expected, original_path)
|
80
|
+
self.class.find_key(me, key, expected, original_path)
|
55
81
|
else
|
56
|
-
o = find_key(me, key, ConfigValueType::OBJECT,
|
82
|
+
o = self.class.find_key(me, key, ConfigValueType::OBJECT,
|
57
83
|
original_path.sub_path(0, original_path.length - rest.length))
|
58
84
|
raise "Error: object o is nil" unless not o.nil?
|
59
85
|
find(o, rest, expected, original_path)
|
60
86
|
end
|
61
87
|
end
|
62
88
|
|
89
|
+
def find3(path_expression, expected, original_path)
|
90
|
+
find(@object, path_expression, expected, original_path)
|
91
|
+
end
|
92
|
+
|
93
|
+
def find2(path_expression, expected)
|
94
|
+
path = Path.new_path(path_expression)
|
95
|
+
find3(path, expected, path)
|
96
|
+
end
|
97
|
+
|
98
|
+
def ==(other)
|
99
|
+
if other.is_a? Hocon::Impl::SimpleConfig
|
100
|
+
@object == other.object
|
101
|
+
else
|
102
|
+
false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def hash
|
107
|
+
41 * @object.hash
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.find_key_or_null(me, key, expected, original_path)
|
111
|
+
v = me.peek_assuming_resolved(key, original_path)
|
112
|
+
|
113
|
+
if v.nil?
|
114
|
+
raise Hocon::ConfigError::ConfigMissingError.new(nil, original_path.render, nil)
|
115
|
+
end
|
116
|
+
|
117
|
+
if not expected.nil?
|
118
|
+
v = Hocon::Impl::DefaultTransformer.transform(v, expected)
|
119
|
+
end
|
120
|
+
|
121
|
+
if (not expected.nil?) && (v.value_type != expected && v.value_type != Hocon::ConfigValueType::NULL)
|
122
|
+
raise Hocon::ConfigError::ConfigWrongTypeError.with_expected_actual(v.origin,
|
123
|
+
original_path.render,
|
124
|
+
expected.name,
|
125
|
+
Hocon::ConfigValueType.name(v.value_type))
|
126
|
+
else
|
127
|
+
return v
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.find_or_null(me, path, expected, original_path)
|
132
|
+
begin
|
133
|
+
key = path.first
|
134
|
+
remainder = path.remainder
|
135
|
+
|
136
|
+
if remainder.nil?
|
137
|
+
return self.find_key_or_null(me, key, expected, original_path)
|
138
|
+
else
|
139
|
+
o = find_key(me,
|
140
|
+
key,
|
141
|
+
Hocon::ConfigValueType::OBJECT,
|
142
|
+
original_path.sub_path(0, original_path.length - remainder.length))
|
143
|
+
|
144
|
+
if o.nil?
|
145
|
+
raise "Missing key: #{key} on path: #{path}"
|
146
|
+
end
|
147
|
+
|
148
|
+
find_or_null(o, remainder, expected, original_path)
|
149
|
+
end
|
150
|
+
rescue Hocon::ConfigError::ConfigNotResolvedError
|
151
|
+
raise Hocon::Impl::ConfigImpl::improved_not_resolved(path, e)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def is_null?(path_expression)
|
156
|
+
path = Path.new_path(path_expression)
|
157
|
+
v = self.class.find_or_null(@object, path, nil, path)
|
158
|
+
v.value_type == Hocon::ConfigValueType::NULL
|
159
|
+
end
|
160
|
+
|
63
161
|
def get_value(path)
|
64
162
|
parsed_path = Path.new_path(path)
|
65
163
|
find(@object, parsed_path, nil, parsed_path)
|
66
164
|
end
|
67
165
|
|
68
|
-
def
|
166
|
+
def get_boolean(path)
|
167
|
+
v = find2(path, ConfigValueType::BOOLEAN)
|
168
|
+
v.unwrapped
|
169
|
+
end
|
170
|
+
|
171
|
+
def get_config_number(path_expression)
|
69
172
|
path = Path.new_path(path_expression)
|
173
|
+
v = find(@object, path, ConfigValueType::NUMBER, path)
|
174
|
+
v.unwrapped
|
175
|
+
end
|
176
|
+
|
177
|
+
def get_int(path)
|
178
|
+
get_config_number(path)
|
179
|
+
end
|
180
|
+
|
181
|
+
def get_string(path)
|
182
|
+
v = find2(path, ConfigValueType::STRING)
|
183
|
+
v.unwrapped
|
184
|
+
end
|
185
|
+
|
186
|
+
def get_list(path)
|
187
|
+
find2(path, ConfigValueType::LIST)
|
188
|
+
end
|
189
|
+
|
190
|
+
def get_object(path)
|
191
|
+
find2(path, ConfigValueType::OBJECT)
|
192
|
+
end
|
193
|
+
|
194
|
+
def get_config(path)
|
195
|
+
get_object(path).to_config
|
196
|
+
end
|
197
|
+
|
198
|
+
def get_any_ref(path)
|
199
|
+
v = find2(path, nil)
|
200
|
+
v.unwrapped
|
201
|
+
end
|
202
|
+
|
203
|
+
def get_bytes(path)
|
204
|
+
size = null
|
205
|
+
begin
|
206
|
+
size = get_long(path)
|
207
|
+
rescue ConfigWrongTypeError => e
|
208
|
+
v = find2(path, ConfigValueType::STRING)
|
209
|
+
size = self.class.parse_bytes(v.unwrapped, v.origin, path)
|
210
|
+
end
|
211
|
+
size
|
212
|
+
end
|
213
|
+
|
214
|
+
def get_homogeneous_unwrapped_list(path, expected)
|
215
|
+
l = []
|
216
|
+
list = get_list(path)
|
217
|
+
list.each do |cv|
|
218
|
+
if !expected.nil?
|
219
|
+
v = DefaultTransformer.transform(cv, expected)
|
220
|
+
end
|
221
|
+
if v.value_type != expected
|
222
|
+
raise ConfigWrongTypeError.with_expected_actual(origin, path,
|
223
|
+
"list of #{expected.name}",
|
224
|
+
"list of #{v.value_type.name}")
|
225
|
+
end
|
226
|
+
l << v.unwrapped
|
227
|
+
end
|
228
|
+
l
|
229
|
+
end
|
230
|
+
|
231
|
+
def get_boolean_list(path)
|
232
|
+
get_homogeneous_unwrapped_list(path, ConfigValueType::BOOLEAN)
|
233
|
+
end
|
234
|
+
|
235
|
+
def get_number_list(path)
|
236
|
+
get_homogeneous_unwrapped_list(path, ConfigValueType::NUMBER)
|
237
|
+
end
|
238
|
+
|
239
|
+
def get_int_list(path)
|
240
|
+
l = []
|
241
|
+
numbers = get_homogeneous_wrapped_list(path, ConfigValueType::NUMBER)
|
242
|
+
numbers.each do |v|
|
243
|
+
l << v.int_value_range_checked(path)
|
244
|
+
end
|
245
|
+
l
|
246
|
+
end
|
247
|
+
|
248
|
+
def get_double_list(path)
|
249
|
+
l = []
|
250
|
+
numbers = get_number_list(path)
|
251
|
+
numbers.each do |n|
|
252
|
+
l << n.double_value
|
253
|
+
end
|
254
|
+
l
|
255
|
+
end
|
256
|
+
|
257
|
+
def get_string_list(path)
|
258
|
+
get_homogeneous_unwrapped_list(path, ConfigValueType::STRING)
|
259
|
+
end
|
260
|
+
|
261
|
+
def get_object_list(path)
|
262
|
+
get_homogeneous_wrapped_list(path, ConfigValueType::OBJECT)
|
263
|
+
end
|
264
|
+
|
265
|
+
def get_homogeneous_wrapped_list(path, expected)
|
266
|
+
l = []
|
267
|
+
list = get_list(path)
|
268
|
+
list.each do |cv|
|
269
|
+
if !expected.nil?
|
270
|
+
v = DefaultTransformer.transform(cv, expected)
|
271
|
+
end
|
272
|
+
if v.value_type != expected
|
273
|
+
raise ConfigWrongTypeError.with_expected_actual(origin, path,
|
274
|
+
"list of #{expected.name}",
|
275
|
+
"list of #{v.value_type.name}")
|
276
|
+
end
|
277
|
+
l << v
|
278
|
+
end
|
279
|
+
l
|
280
|
+
end
|
281
|
+
|
282
|
+
def has_path_peek(path_expression)
|
283
|
+
path = Path.new_path(path_expression)
|
284
|
+
|
70
285
|
begin
|
71
286
|
peeked = @object.peek_path(path)
|
72
|
-
rescue ConfigNotResolvedError
|
73
|
-
raise Hocon::Impl::ConfigImpl.
|
287
|
+
rescue Hocon::ConfigError::ConfigNotResolvedError
|
288
|
+
raise Hocon::Impl::ConfigImpl.improved_not_resolved(path, e)
|
74
289
|
end
|
290
|
+
|
291
|
+
peeked
|
292
|
+
end
|
293
|
+
|
294
|
+
def has_path?(path_expression)
|
295
|
+
peeked = has_path_peek(path_expression)
|
296
|
+
|
75
297
|
(not peeked.nil?) && peeked.value_type != ConfigValueType::NULL
|
76
298
|
end
|
77
299
|
|
300
|
+
def has_path_or_null?(path)
|
301
|
+
peeked = has_path_peek(path)
|
302
|
+
|
303
|
+
not peeked.nil?
|
304
|
+
end
|
305
|
+
|
306
|
+
def empty?
|
307
|
+
@object.empty?
|
308
|
+
end
|
309
|
+
|
310
|
+
def at_key(key)
|
311
|
+
root.at_key(key)
|
312
|
+
end
|
313
|
+
|
314
|
+
# In java this is an overloaded version of atKey
|
315
|
+
def at_key_with_origin(origin, key)
|
316
|
+
root.at_key_with_origin(origin, key)
|
317
|
+
end
|
318
|
+
|
319
|
+
def with_only_path(path_expression)
|
320
|
+
path = Path.new_path(path_expression)
|
321
|
+
self.class.new(root.with_only_path(path))
|
322
|
+
end
|
323
|
+
|
78
324
|
def without_path(path_expression)
|
79
325
|
path = Path.new_path(path_expression)
|
80
326
|
self.class.new(root.without_path(path))
|
@@ -84,4 +330,12 @@ class Hocon::Impl::SimpleConfig
|
|
84
330
|
path = Path.new_path(path_expression)
|
85
331
|
self.class.new(root.with_value(path, v))
|
86
332
|
end
|
87
|
-
|
333
|
+
|
334
|
+
def to_fallback_value
|
335
|
+
@object
|
336
|
+
end
|
337
|
+
|
338
|
+
def with_fallback(other)
|
339
|
+
@object.with_fallback(other).to_config
|
340
|
+
end
|
341
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'hocon/impl'
|
4
|
+
require 'hocon/parser/config_document'
|
5
|
+
require 'hocon/impl/config_document_parser'
|
6
|
+
|
7
|
+
class Hocon::Impl::SimpleConfigDocument
|
8
|
+
include Hocon::Parser::ConfigDocument
|
9
|
+
|
10
|
+
def initialize(parsed_node, parse_options)
|
11
|
+
@config_node_tree = parsed_node
|
12
|
+
@parse_options = parse_options
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_value(path, new_value)
|
16
|
+
origin = Hocon::Impl::SimpleConfigOrigin.new_simple("single value parsing")
|
17
|
+
reader = StringIO.new(new_value)
|
18
|
+
tokens = Hocon::Impl::Tokenizer.tokenize(origin, reader, @parse_options.syntax)
|
19
|
+
parsed_value = Hocon::Impl::ConfigDocumentParser.parse_value(tokens, origin, @parse_options)
|
20
|
+
reader.close
|
21
|
+
|
22
|
+
self.class.new(@config_node_tree.set_value(path, parsed_value, @parse_options.syntax), @parse_options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_config_value(path, new_value)
|
26
|
+
set_value(path, new_value.render)
|
27
|
+
end
|
28
|
+
|
29
|
+
def remove_value(path)
|
30
|
+
self.class.new(@config_node_tree.set_value(path, nil, @parse_options.syntax), @parse_options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def has_value?(path)
|
34
|
+
@config_node_tree.has_value(path)
|
35
|
+
end
|
36
|
+
|
37
|
+
def render
|
38
|
+
@config_node_tree.render
|
39
|
+
end
|
40
|
+
|
41
|
+
def ==(other)
|
42
|
+
other.class.ancestors.include?(Hocon::Parser::ConfigDocument) && render == other.render
|
43
|
+
end
|
44
|
+
|
45
|
+
def hash
|
46
|
+
render.hash
|
47
|
+
end
|
48
|
+
end
|
@@ -1,10 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'hocon/impl'
|
2
4
|
require 'hocon/impl/resolve_status'
|
3
5
|
require 'hocon/config_value_type'
|
6
|
+
require 'hocon/config_error'
|
4
7
|
require 'hocon/impl/abstract_config_object'
|
8
|
+
require 'forwardable'
|
9
|
+
require 'hocon/impl/unsupported_operation_error'
|
10
|
+
require 'hocon/impl/resolve_result'
|
11
|
+
require 'hocon/impl/container'
|
12
|
+
require 'hocon/config_list'
|
13
|
+
|
14
|
+
class Hocon::Impl::SimpleConfigList
|
15
|
+
include Hocon::Impl::Container
|
16
|
+
include Hocon::ConfigList
|
17
|
+
include Hocon::Impl::AbstractConfigValue
|
18
|
+
extend Forwardable
|
5
19
|
|
6
|
-
class Hocon::Impl::SimpleConfigList < Hocon::Impl::AbstractConfigValue
|
7
20
|
ResolveStatus = Hocon::Impl::ResolveStatus
|
21
|
+
ResolveResult = Hocon::Impl::ResolveResult
|
22
|
+
ConfigBugOrBrokenError = Hocon::ConfigError::ConfigBugOrBrokenError
|
8
23
|
|
9
24
|
def initialize(origin, value, status = ResolveStatus.from_values(value))
|
10
25
|
super(origin)
|
@@ -13,10 +28,14 @@ class Hocon::Impl::SimpleConfigList < Hocon::Impl::AbstractConfigValue
|
|
13
28
|
|
14
29
|
# kind of an expensive debug check (makes this constructor pointless)
|
15
30
|
if status != ResolveStatus.from_values(value)
|
16
|
-
raise
|
31
|
+
raise ConfigBugOrBrokenError, "SimpleConfigList created with wrong resolve status: #{self}"
|
17
32
|
end
|
18
33
|
end
|
19
34
|
|
35
|
+
attr_reader :value
|
36
|
+
|
37
|
+
def_delegators :@value, :[], :include?, :empty?, :size, :index, :rindex, :each, :map
|
38
|
+
|
20
39
|
def value_type
|
21
40
|
Hocon::ConfigValueType::LIST
|
22
41
|
end
|
@@ -25,6 +44,143 @@ class Hocon::Impl::SimpleConfigList < Hocon::Impl::AbstractConfigValue
|
|
25
44
|
@value.map { |v| v.unwrapped }
|
26
45
|
end
|
27
46
|
|
47
|
+
def resolve_status
|
48
|
+
ResolveStatus.from_boolean(@resolved)
|
49
|
+
end
|
50
|
+
|
51
|
+
def replace_child(child, replacement)
|
52
|
+
new_list = replace_child_in_list(@value, child, replacement)
|
53
|
+
if new_list.nil?
|
54
|
+
nil
|
55
|
+
else
|
56
|
+
# we use the constructor flavor that will recompute the resolve status
|
57
|
+
SimpleConfigList.new(origin, new_list)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def has_descendant?(descendant)
|
62
|
+
Hocon::Impl::AbstractConfigValue.has_descendant_in_list?(@value, descendant)
|
63
|
+
end
|
64
|
+
|
65
|
+
def modify(modifier, new_resolve_status)
|
66
|
+
begin
|
67
|
+
modify_may_throw(modifier, new_resolve_status)
|
68
|
+
rescue Hocon::ConfigError => e
|
69
|
+
raise e
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def modify_may_throw(modifier, new_resolve_status)
|
74
|
+
# lazy-create for optimization
|
75
|
+
changed = nil
|
76
|
+
i = 0
|
77
|
+
@value.each { |v|
|
78
|
+
modified = modifier.modify_child_may_throw(nil, v)
|
79
|
+
|
80
|
+
# lazy-create the new list if required
|
81
|
+
if changed == nil && !modified.equal?(v)
|
82
|
+
changed = []
|
83
|
+
j = 0
|
84
|
+
while j < i
|
85
|
+
changed << @value[j]
|
86
|
+
j += 1
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# once the new list is created, all elements
|
91
|
+
# have to go in it.if modifyChild returned
|
92
|
+
# null, we drop that element.
|
93
|
+
if changed != nil && modified != nil
|
94
|
+
changed << modified
|
95
|
+
end
|
96
|
+
|
97
|
+
i += 1
|
98
|
+
}
|
99
|
+
|
100
|
+
if changed != nil
|
101
|
+
if new_resolve_status != nil
|
102
|
+
self.class.new(origin, changed, new_resolve_status)
|
103
|
+
else
|
104
|
+
self.class.new(origin, changed)
|
105
|
+
end
|
106
|
+
else
|
107
|
+
self
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class ResolveModifier
|
112
|
+
attr_reader :context, :source
|
113
|
+
def initialize(context, source)
|
114
|
+
@context = context
|
115
|
+
@source = source
|
116
|
+
end
|
117
|
+
|
118
|
+
def modify_child_may_throw(key, v)
|
119
|
+
result = @context.resolve(v, source)
|
120
|
+
@context = result.context
|
121
|
+
result.value
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def resolve_substitutions(context, source)
|
126
|
+
if @resolved
|
127
|
+
return Hocon::Impl::ResolveResult.make(context, self)
|
128
|
+
end
|
129
|
+
|
130
|
+
if context.is_restricted_to_child
|
131
|
+
# if a list restricts to a child path, then it has no child paths,
|
132
|
+
# so nothing to do.
|
133
|
+
Hocon::Impl::ResolveResult.make(context, self)
|
134
|
+
else
|
135
|
+
begin
|
136
|
+
modifier = ResolveModifier.new(context, source.push_parent(self))
|
137
|
+
value = modify_may_throw(modifier, context.options.allow_unresolved ? nil : ResolveStatus::RESOLVED)
|
138
|
+
Hocon::Impl::ResolveResult.make(modifier.context, value)
|
139
|
+
rescue NotPossibleToResolve => e
|
140
|
+
raise e
|
141
|
+
rescue RuntimeError => e
|
142
|
+
raise e
|
143
|
+
rescue Exception => e
|
144
|
+
raise ConfigBugOrBrokenError.new("unexpected exception", e)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def relativized(prefix)
|
150
|
+
modifier = Class.new do
|
151
|
+
include Hocon::Impl::AbstractConfigValue::NoExceptionsModifier
|
152
|
+
|
153
|
+
# prefix isn't in scope inside of a def, but it is in scope inside of Class.new
|
154
|
+
# so manually define a method that has access to prefix
|
155
|
+
# I feel dirty
|
156
|
+
define_method(:modify_child) do |key, v|
|
157
|
+
v.relativized(prefix)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
modify(modifier.new, resolve_status)
|
162
|
+
end
|
163
|
+
|
164
|
+
def can_equal(other)
|
165
|
+
other.is_a?(self.class)
|
166
|
+
end
|
167
|
+
|
168
|
+
def ==(other)
|
169
|
+
# note that "origin" is deliberately NOT part of equality
|
170
|
+
if other.is_a?(self.class)
|
171
|
+
# optimization to avoid unwrapped() for two ConfigList
|
172
|
+
can_equal(other) &&
|
173
|
+
(value.equal?(other.value) || (value == other.value))
|
174
|
+
else
|
175
|
+
false
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def hash
|
180
|
+
# note that "origin" is deliberately NOT part of equality
|
181
|
+
value.hash
|
182
|
+
end
|
183
|
+
|
28
184
|
def render_value_to_sb(sb, indent_size, at_root, options)
|
29
185
|
if @value.empty?
|
30
186
|
sb << "[]"
|
@@ -35,10 +191,13 @@ class Hocon::Impl::SimpleConfigList < Hocon::Impl::AbstractConfigValue
|
|
35
191
|
end
|
36
192
|
@value.each do |v|
|
37
193
|
if options.origin_comments?
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
194
|
+
lines = v.origin.description.split("\n")
|
195
|
+
lines.each do |l|
|
196
|
+
Hocon::Impl::AbstractConfigValue.indent(sb, indent_size + 1, options)
|
197
|
+
sb << "# "
|
198
|
+
sb << l
|
199
|
+
sb << "\n"
|
200
|
+
end
|
42
201
|
end
|
43
202
|
if options.comments?
|
44
203
|
v.origin.comments.each do |comment|
|
@@ -47,7 +206,7 @@ class Hocon::Impl::SimpleConfigList < Hocon::Impl::AbstractConfigValue
|
|
47
206
|
sb << "\n"
|
48
207
|
end
|
49
208
|
end
|
50
|
-
indent(sb, indent_size + 1, options)
|
209
|
+
Hocon::Impl::AbstractConfigValue.indent(sb, indent_size + 1, options)
|
51
210
|
|
52
211
|
v.render_value_to_sb(sb, indent_size + 1, at_root, options)
|
53
212
|
sb << ","
|
@@ -63,13 +222,128 @@ class Hocon::Impl::SimpleConfigList < Hocon::Impl::AbstractConfigValue
|
|
63
222
|
if options.formatted?
|
64
223
|
sb.pos = sb.pos - 1 # also chop comma
|
65
224
|
sb << "\n"
|
66
|
-
indent(sb, indent_size, options)
|
225
|
+
Hocon::Impl::AbstractConfigValue.indent(sb, indent_size, options)
|
67
226
|
end
|
68
227
|
sb << "]"
|
69
228
|
end
|
70
229
|
end
|
71
230
|
|
231
|
+
def contains?(o)
|
232
|
+
value.include?(o)
|
233
|
+
end
|
234
|
+
|
235
|
+
def include_all?(value_list)
|
236
|
+
value_list.all? { |v| @value.include?(v)}
|
237
|
+
end
|
238
|
+
|
239
|
+
def contains_all?(c)
|
240
|
+
include_all?(c)
|
241
|
+
end
|
242
|
+
|
243
|
+
def get(index)
|
244
|
+
value[index]
|
245
|
+
end
|
246
|
+
|
247
|
+
def index_of(o)
|
248
|
+
value.index(o)
|
249
|
+
end
|
250
|
+
|
251
|
+
def is_empty
|
252
|
+
empty?
|
253
|
+
end
|
254
|
+
|
255
|
+
# Skipping upstream definition of "iterator", because that's not really a thing
|
256
|
+
# in Ruby.
|
257
|
+
|
258
|
+
def last_index_of(o)
|
259
|
+
value.rindex(o)
|
260
|
+
end
|
261
|
+
|
262
|
+
# skipping upstream definitions of "wrapListIterator", "listIterator", and
|
263
|
+
# "listIterator(int)", because those don't really apply in Ruby.
|
264
|
+
|
265
|
+
def sub_list(from_index, to_index)
|
266
|
+
value[from_index..to_index]
|
267
|
+
end
|
268
|
+
|
269
|
+
def to_array
|
270
|
+
value
|
271
|
+
end
|
272
|
+
|
273
|
+
def we_are_immutable(method)
|
274
|
+
Hocon::Impl::UnsupportedOperationError.new("ConfigList is immutable, you can't call List. '#{method}'")
|
275
|
+
end
|
276
|
+
|
277
|
+
def add(e)
|
278
|
+
raise we_are_immutable("add")
|
279
|
+
end
|
280
|
+
|
281
|
+
def add_at(index, element)
|
282
|
+
raise we_are_immutable("add_at")
|
283
|
+
end
|
284
|
+
|
285
|
+
def add_all(c)
|
286
|
+
raise we_are_immutable("add_all")
|
287
|
+
end
|
288
|
+
|
289
|
+
def add_all_at(index, c)
|
290
|
+
raise we_are_immutable("add_all_at")
|
291
|
+
end
|
292
|
+
|
293
|
+
def clear
|
294
|
+
raise we_are_immutable("clear")
|
295
|
+
end
|
296
|
+
|
297
|
+
def remove(o)
|
298
|
+
raise we_are_immutable("remove")
|
299
|
+
end
|
300
|
+
|
301
|
+
def remove_at(i)
|
302
|
+
raise we_are_immutable("remove_at")
|
303
|
+
end
|
304
|
+
|
305
|
+
def delete(o)
|
306
|
+
raise we_are_immutable("delete")
|
307
|
+
end
|
308
|
+
|
309
|
+
def remove_all(c)
|
310
|
+
raise we_are_immutable("remove_all")
|
311
|
+
end
|
312
|
+
|
313
|
+
def retain_all(c)
|
314
|
+
raise we_are_immutable("retain_all")
|
315
|
+
end
|
316
|
+
|
317
|
+
def set(index, element)
|
318
|
+
raise we_are_immutable("set")
|
319
|
+
end
|
320
|
+
|
321
|
+
def []=(index, element)
|
322
|
+
raise we_are_immutable("[]=")
|
323
|
+
end
|
324
|
+
|
325
|
+
def push(e)
|
326
|
+
raise we_are_immutable("push")
|
327
|
+
end
|
328
|
+
|
329
|
+
def <<(e)
|
330
|
+
raise we_are_immutable("<<")
|
331
|
+
end
|
332
|
+
|
72
333
|
def new_copy(origin)
|
73
334
|
Hocon::Impl::SimpleConfigList.new(origin, @value)
|
74
335
|
end
|
336
|
+
|
337
|
+
def concatenate(other)
|
338
|
+
combined_origin = Hocon::Impl::SimpleConfigOrigin.merge_two_origins(origin, other.origin)
|
339
|
+
combined = value + other.value
|
340
|
+
Hocon::Impl::SimpleConfigList.new(combined_origin, combined)
|
341
|
+
end
|
342
|
+
|
343
|
+
# Skipping upstream "writeReplace" until we see that we need it for something
|
344
|
+
|
345
|
+
def with_origin(origin)
|
346
|
+
super(origin)
|
347
|
+
end
|
348
|
+
|
75
349
|
end
|