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,28 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'hocon/impl'
|
2
4
|
require 'hocon/impl/simple_config_origin'
|
3
5
|
require 'hocon/impl/abstract_config_object'
|
4
6
|
require 'hocon/impl/resolve_status'
|
7
|
+
require 'hocon/impl/resolve_result'
|
8
|
+
require 'hocon/impl/path'
|
5
9
|
require 'hocon/config_error'
|
6
10
|
require 'set'
|
11
|
+
require 'forwardable'
|
12
|
+
|
7
13
|
|
8
|
-
class Hocon::Impl::SimpleConfigObject
|
14
|
+
class Hocon::Impl::SimpleConfigObject
|
15
|
+
include Hocon::Impl::AbstractConfigObject
|
16
|
+
extend Forwardable
|
9
17
|
|
10
18
|
ConfigBugOrBrokenError = Hocon::ConfigError::ConfigBugOrBrokenError
|
11
19
|
ResolveStatus = Hocon::Impl::ResolveStatus
|
20
|
+
ResolveResult = Hocon::Impl::ResolveResult
|
12
21
|
SimpleConfigOrigin = Hocon::Impl::SimpleConfigOrigin
|
22
|
+
Path = Hocon::Impl::Path
|
13
23
|
|
14
|
-
def self.empty_missing(base_origin)
|
15
|
-
self.new(
|
16
|
-
Hocon::Impl::SimpleConfigOrigin.new_simple("#{base_origin.description} (not found)"),
|
17
|
-
{})
|
18
|
-
end
|
19
24
|
|
20
|
-
def initialize(origin,
|
21
|
-
|
22
|
-
|
25
|
+
def initialize(origin,
|
26
|
+
value,
|
27
|
+
status = Hocon::Impl::ResolveStatus.from_values(value.values),
|
28
|
+
ignores_fallbacks = false)
|
23
29
|
super(origin)
|
24
30
|
if value.nil?
|
25
|
-
raise
|
31
|
+
raise ConfigBugOrBrokenError, "creating config object with null map"
|
26
32
|
end
|
27
33
|
@value = value
|
28
34
|
@resolved = (status == Hocon::Impl::ResolveStatus::RESOLVED)
|
@@ -30,15 +36,170 @@ class Hocon::Impl::SimpleConfigObject < Hocon::Impl::AbstractConfigObject
|
|
30
36
|
|
31
37
|
# Kind of an expensive debug check. Comment out?
|
32
38
|
if status != Hocon::Impl::ResolveStatus.from_values(value.values)
|
33
|
-
raise
|
39
|
+
raise ConfigBugOrBrokenError, "Wrong resolved status on #{self}"
|
34
40
|
end
|
35
41
|
end
|
36
42
|
|
37
43
|
attr_reader :value
|
44
|
+
# To support accessing ConfigObjects like a hash
|
45
|
+
def_delegators :@value, :[], :has_key?, :has_value?, :empty?, :size, :keys, :values, :each, :map
|
46
|
+
|
47
|
+
|
48
|
+
def with_only_key(key)
|
49
|
+
with_only_path(Path.new_key(key))
|
50
|
+
end
|
51
|
+
|
52
|
+
def without_key(key)
|
53
|
+
without_path(Path.new_key(key))
|
54
|
+
end
|
55
|
+
|
56
|
+
# gets the object with only the path if the path
|
57
|
+
# exists, otherwise null if it doesn't. this ensures
|
58
|
+
# that if we have { a : { b : 42 } } and do
|
59
|
+
# withOnlyPath("a.b.c") that we don't keep an empty
|
60
|
+
# "a" object.
|
61
|
+
def with_only_path_or_nil(path)
|
62
|
+
key = path.first
|
63
|
+
path_next = path.remainder
|
64
|
+
v = value[key]
|
65
|
+
|
66
|
+
if ! path_next.nil?
|
67
|
+
if (!v.nil?) && (v.is_a?(Hocon::Impl::AbstractConfigObject))
|
68
|
+
v = v.with_only_path_or_nil(path_next)
|
69
|
+
else
|
70
|
+
# if the path has more elements but we don't have an object,
|
71
|
+
# then the rest of the path does not exist.
|
72
|
+
v = nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if v.nil?
|
77
|
+
nil
|
78
|
+
else
|
79
|
+
self.class.new(origin, {key => v}, v.resolve_status, @ignores_fallbacks)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def with_only_path(path)
|
84
|
+
o = with_only_path_or_nil(path)
|
85
|
+
if o.nil?
|
86
|
+
self.class.new(origin, {}, ResolveStatus::RESOLVED, @ignores_fallbacks)
|
87
|
+
else
|
88
|
+
o
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def without_path(path)
|
93
|
+
key = path.first
|
94
|
+
remainder = path.remainder
|
95
|
+
v = @value[key]
|
96
|
+
|
97
|
+
if (not v.nil?) && (not remainder.nil?) && v.is_a?(Hocon::Impl::AbstractConfigObject)
|
98
|
+
v = v.without_path(remainder)
|
99
|
+
updated = @value.clone
|
100
|
+
updated[key] = v
|
101
|
+
self.class.new(origin,
|
102
|
+
updated,
|
103
|
+
ResolveStatus.from_values(updated.values), @ignores_fallbacks)
|
104
|
+
elsif (not remainder.nil?) || v.nil?
|
105
|
+
return self
|
106
|
+
else
|
107
|
+
smaller = Hash.new
|
108
|
+
@value.each do |old_key, old_value|
|
109
|
+
unless old_key == key
|
110
|
+
smaller[old_key] = old_value
|
111
|
+
end
|
112
|
+
end
|
113
|
+
self.class.new(origin,
|
114
|
+
smaller,
|
115
|
+
ResolveStatus.from_values(smaller.values), @ignores_fallbacks)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def with_value(path, v)
|
120
|
+
key = path.first
|
121
|
+
remainder = path.remainder
|
122
|
+
|
123
|
+
if remainder.nil?
|
124
|
+
with_key_value(key, v)
|
125
|
+
else
|
126
|
+
child = @value[key]
|
127
|
+
if (not child.nil?) && child.is_a?(Hocon::Impl::AbstractConfigObject)
|
128
|
+
return with_key_value(key, child.with_value(remainder, v))
|
129
|
+
else
|
130
|
+
subtree = v.at_path_with_origin(
|
131
|
+
SimpleConfigOrigin.new_simple("with_value(#{remainder.render})"), remainder)
|
132
|
+
with_key_value(key, subtree.root)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def with_key_value(key, v)
|
138
|
+
if v.nil?
|
139
|
+
raise ConfigBugOrBrokenError.new("Trying to store null ConfigValue in a ConfigObject")
|
140
|
+
end
|
141
|
+
|
142
|
+
new_map = Hash.new
|
143
|
+
if @value.empty?
|
144
|
+
new_map[key] = v
|
145
|
+
else
|
146
|
+
new_map = @value.clone
|
147
|
+
new_map[key] = v
|
148
|
+
end
|
149
|
+
self.class.new(origin, new_map, ResolveStatus.from_values(new_map.values), @ignores_fallbacks)
|
150
|
+
end
|
151
|
+
|
152
|
+
def attempt_peek_with_partial_resolve(key)
|
153
|
+
@value[key]
|
154
|
+
end
|
38
155
|
|
39
156
|
def new_copy_with_status(new_status, new_origin, new_ignores_fallbacks = nil)
|
40
|
-
|
41
|
-
|
157
|
+
self.class.new(new_origin, @value, new_status, new_ignores_fallbacks)
|
158
|
+
end
|
159
|
+
|
160
|
+
def with_fallbacks_ignored()
|
161
|
+
if @ignores_fallbacks
|
162
|
+
self
|
163
|
+
else
|
164
|
+
new_copy_with_status(resolve_status, origin, true)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def resolve_status
|
169
|
+
ResolveStatus.from_boolean(@resolved)
|
170
|
+
end
|
171
|
+
|
172
|
+
def replace_child(child, replacement)
|
173
|
+
new_children = @value.clone
|
174
|
+
new_children.each do |old, old_value|
|
175
|
+
if old_value.equal?(child)
|
176
|
+
if replacement != nil
|
177
|
+
new_children[old] = replacement
|
178
|
+
else
|
179
|
+
new_children.delete(old)
|
180
|
+
end
|
181
|
+
|
182
|
+
return self.class.new(origin, new_children, ResolveStatus.from_values(new_children.values),
|
183
|
+
@ignores_fallbacks)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
raise ConfigBugOrBrokenError, "SimpleConfigObject.replaceChild did not find #{child} in #{self}"
|
187
|
+
end
|
188
|
+
|
189
|
+
def has_descendant?(descendant)
|
190
|
+
value.values.each do |child|
|
191
|
+
if child.equal?(descendant)
|
192
|
+
return true
|
193
|
+
end
|
194
|
+
end
|
195
|
+
# now do the expensive search
|
196
|
+
value.values.each do |child|
|
197
|
+
if child.is_a?(Hocon::Impl::Container) && child.has_descendant?(descendant)
|
198
|
+
return true
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
false
|
42
203
|
end
|
43
204
|
|
44
205
|
def ignores_fallbacks?
|
@@ -46,14 +207,18 @@ class Hocon::Impl::SimpleConfigObject < Hocon::Impl::AbstractConfigObject
|
|
46
207
|
end
|
47
208
|
|
48
209
|
def unwrapped
|
49
|
-
|
210
|
+
m = {}
|
211
|
+
@value.each do |k,v|
|
212
|
+
m[k] = v.unwrapped
|
213
|
+
end
|
214
|
+
m
|
50
215
|
end
|
51
216
|
|
52
217
|
def merged_with_object(abstract_fallback)
|
53
218
|
require_not_ignoring_fallbacks
|
54
219
|
|
55
220
|
unless abstract_fallback.is_a?(Hocon::Impl::SimpleConfigObject)
|
56
|
-
raise
|
221
|
+
raise ConfigBugOrBrokenError, "should not be reached (merging non-SimpleConfigObject)"
|
57
222
|
end
|
58
223
|
|
59
224
|
fallback = abstract_fallback
|
@@ -87,46 +252,204 @@ class Hocon::Impl::SimpleConfigObject < Hocon::Impl::AbstractConfigObject
|
|
87
252
|
new_ignores_fallbacks = fallback.ignores_fallbacks?
|
88
253
|
|
89
254
|
if changed
|
90
|
-
Hocon::Impl::SimpleConfigObject.new(merge_origins([self, fallback]),
|
91
|
-
|
92
|
-
|
255
|
+
Hocon::Impl::SimpleConfigObject.new(Hocon::Impl::AbstractConfigObject.merge_origins([self, fallback]),
|
256
|
+
merged, new_resolve_status,
|
257
|
+
new_ignores_fallbacks)
|
93
258
|
elsif (new_resolve_status != resolve_status) || (new_ignores_fallbacks != ignores_fallbacks?)
|
94
|
-
|
259
|
+
new_copy_with_status(new_resolve_status, origin, new_ignores_fallbacks)
|
95
260
|
else
|
96
261
|
self
|
97
262
|
end
|
98
263
|
end
|
99
264
|
|
100
|
-
def
|
265
|
+
def modify(modifier)
|
266
|
+
begin
|
267
|
+
modify_may_throw(modifier)
|
268
|
+
rescue Hocon::ConfigError => e
|
269
|
+
raise e
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def modify_may_throw(modifier)
|
274
|
+
changes = nil
|
275
|
+
keys.each do |k|
|
276
|
+
v = value[k]
|
277
|
+
# "modified" may be null, which means remove the child;
|
278
|
+
# to do that we put null in the "changes" map.
|
279
|
+
modified = modifier.modify_child_may_throw(k, v)
|
280
|
+
if ! modified.equal?(v)
|
281
|
+
if changes.nil?
|
282
|
+
changes = {}
|
283
|
+
end
|
284
|
+
changes[k] = modified
|
285
|
+
end
|
286
|
+
end
|
287
|
+
if changes.nil?
|
288
|
+
self
|
289
|
+
else
|
290
|
+
modified = {}
|
291
|
+
saw_unresolved = false
|
292
|
+
keys.each do |k|
|
293
|
+
if changes.has_key?(k)
|
294
|
+
new_value = changes[k]
|
295
|
+
if ! new_value.nil?
|
296
|
+
modified[k] = new_value
|
297
|
+
if new_value.resolve_status == ResolveStatus::UNRESOLVED
|
298
|
+
saw_unresolved = true
|
299
|
+
end
|
300
|
+
else
|
301
|
+
# remove this child; don't put it in the new map
|
302
|
+
end
|
303
|
+
else
|
304
|
+
new_value = value[k]
|
305
|
+
modified[k] = new_value
|
306
|
+
if new_value.resolve_status == ResolveStatus::UNRESOLVED
|
307
|
+
saw_unresolved = true
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
self.class.new(origin, modified,
|
312
|
+
saw_unresolved ? ResolveStatus::UNRESOLVED : ResolveStatus::RESOLVED,
|
313
|
+
@ignores_fallbacks)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
|
318
|
+
class ResolveModifier
|
319
|
+
|
320
|
+
attr_accessor :context
|
321
|
+
attr_reader :source
|
322
|
+
|
323
|
+
def initialize(context, source)
|
324
|
+
@context = context
|
325
|
+
@source = source
|
326
|
+
@original_restrict = context.restrict_to_child
|
327
|
+
end
|
328
|
+
|
329
|
+
def modify_child_may_throw(key, v)
|
330
|
+
if @context.is_restricted_to_child
|
331
|
+
if key == @context.restrict_to_child.first
|
332
|
+
remainder = @context.restrict_to_child.remainder
|
333
|
+
if remainder != nil
|
334
|
+
result = @context.restrict(remainder).resolve(v, @source)
|
335
|
+
@context = result.context.unrestricted.restrict(@original_restrict)
|
336
|
+
return result.value
|
337
|
+
else
|
338
|
+
# we don't want to resolve the leaf child
|
339
|
+
return v
|
340
|
+
end
|
341
|
+
else
|
342
|
+
# not in the restrictToChild path
|
343
|
+
return v
|
344
|
+
end
|
345
|
+
else
|
346
|
+
# no restrictToChild, resolve everything
|
347
|
+
result = @context.unrestricted.resolve(v, @source)
|
348
|
+
@context = result.context.unrestricted.restrict(@original_restrict)
|
349
|
+
result.value
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
def resolve_substitutions(context, source)
|
355
|
+
if resolve_status == ResolveStatus::RESOLVED
|
356
|
+
return ResolveResult.make(context, self)
|
357
|
+
end
|
358
|
+
|
359
|
+
source_with_parent = source.push_parent(self)
|
360
|
+
|
361
|
+
begin
|
362
|
+
modifier = ResolveModifier.new(context, source_with_parent)
|
363
|
+
|
364
|
+
value = modify_may_throw(modifier)
|
365
|
+
ResolveResult.make(modifier.context, value)
|
366
|
+
|
367
|
+
rescue NotPossibleToResolve => e
|
368
|
+
raise e
|
369
|
+
rescue Hocon::ConfigError => e
|
370
|
+
raise e
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
def relativized(prefix)
|
375
|
+
|
376
|
+
modifier = Class.new do
|
377
|
+
include Hocon::Impl::AbstractConfigValue::NoExceptionsModifier
|
378
|
+
|
379
|
+
# prefix isn't in scope inside of a def, but it is in scope inside of Class.new
|
380
|
+
# so manually define a method that has access to prefix
|
381
|
+
# I feel dirty
|
382
|
+
define_method(:modify_child) do |key, v|
|
383
|
+
v.relativized(prefix)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
modify(modifier.new)
|
388
|
+
end
|
389
|
+
|
390
|
+
class RenderComparator
|
391
|
+
def self.all_digits?(s)
|
392
|
+
s =~ /^\d+$/
|
393
|
+
end
|
394
|
+
|
395
|
+
# This is supposed to sort numbers before strings,
|
396
|
+
# and sort the numbers numerically. The point is
|
397
|
+
# to make objects which are really list-like
|
398
|
+
# (numeric indices) appear in order.
|
399
|
+
def self.sort(arr)
|
400
|
+
arr.sort do |a, b|
|
401
|
+
a_digits = all_digits?(a)
|
402
|
+
b_digits = all_digits?(b)
|
403
|
+
if a_digits && b_digits
|
404
|
+
Integer(a) <=> Integer(b)
|
405
|
+
elsif a_digits
|
406
|
+
-1
|
407
|
+
elsif b_digits
|
408
|
+
1
|
409
|
+
else
|
410
|
+
a <=> b
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
def render_value_to_sb(sb, indent, at_root, options)
|
101
417
|
if empty?
|
102
418
|
sb << "{}"
|
103
419
|
else
|
104
420
|
outer_braces = options.json? || !at_root
|
105
421
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
indent_size + 1
|
113
|
-
else
|
114
|
-
indent_size
|
422
|
+
if outer_braces
|
423
|
+
inner_indent = indent + 1
|
424
|
+
sb << "{"
|
425
|
+
|
426
|
+
if options.formatted?
|
427
|
+
sb << "\n"
|
115
428
|
end
|
429
|
+
else
|
430
|
+
inner_indent = indent
|
431
|
+
end
|
116
432
|
|
117
433
|
separator_count = 0
|
118
|
-
|
434
|
+
sorted_keys = RenderComparator.sort(keys)
|
435
|
+
sorted_keys.each do |k|
|
119
436
|
v = @value[k]
|
120
437
|
|
121
438
|
if options.origin_comments?
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
439
|
+
lines = v.origin.description.split("\n")
|
440
|
+
lines.each { |l|
|
441
|
+
Hocon::Impl::AbstractConfigValue.indent(sb, indent + 1, options)
|
442
|
+
sb << '#'
|
443
|
+
unless l.empty?
|
444
|
+
sb << ' '
|
445
|
+
end
|
446
|
+
sb << l
|
447
|
+
sb << "\n"
|
448
|
+
}
|
126
449
|
end
|
127
450
|
if options.comments?
|
128
451
|
v.origin.comments.each do |comment|
|
129
|
-
indent(sb, inner_indent, options)
|
452
|
+
Hocon::Impl::AbstractConfigValue.indent(sb, inner_indent, options)
|
130
453
|
sb << "#"
|
131
454
|
if !comment.start_with?(" ")
|
132
455
|
sb << " "
|
@@ -135,7 +458,7 @@ class Hocon::Impl::SimpleConfigObject < Hocon::Impl::AbstractConfigObject
|
|
135
458
|
sb << "\n"
|
136
459
|
end
|
137
460
|
end
|
138
|
-
indent(sb, inner_indent, options)
|
461
|
+
Hocon::Impl::AbstractConfigValue.indent(sb, inner_indent, options)
|
139
462
|
v.render_to_sb(sb, inner_indent, false, k.to_s, options)
|
140
463
|
|
141
464
|
if options.formatted?
|
@@ -161,7 +484,7 @@ class Hocon::Impl::SimpleConfigObject < Hocon::Impl::AbstractConfigObject
|
|
161
484
|
if options.formatted?
|
162
485
|
sb << "\n" # put a newline back
|
163
486
|
if outer_braces
|
164
|
-
indent(sb,
|
487
|
+
Hocon::Impl::AbstractConfigValue.indent(sb, indent, options)
|
165
488
|
end
|
166
489
|
end
|
167
490
|
sb << "}"
|
@@ -172,74 +495,87 @@ class Hocon::Impl::SimpleConfigObject < Hocon::Impl::AbstractConfigObject
|
|
172
495
|
end
|
173
496
|
end
|
174
497
|
|
498
|
+
def self.map_equals(a, b)
|
499
|
+
if a.equal?(b)
|
500
|
+
return true
|
501
|
+
end
|
175
502
|
|
176
|
-
|
177
|
-
|
178
|
-
|
503
|
+
# Hashes aren't ordered in ruby, so sort first
|
504
|
+
if not a.keys.sort == b.keys.sort
|
505
|
+
return false
|
506
|
+
end
|
507
|
+
|
508
|
+
a.keys.each do |key|
|
509
|
+
if a[key] != b[key]
|
510
|
+
return false
|
511
|
+
end
|
512
|
+
end
|
179
513
|
|
180
|
-
|
181
|
-
@value.empty?
|
514
|
+
true
|
182
515
|
end
|
183
516
|
|
184
|
-
def
|
517
|
+
def get(key)
|
185
518
|
@value[key]
|
186
519
|
end
|
187
520
|
|
188
|
-
def
|
189
|
-
|
190
|
-
|
191
|
-
|
521
|
+
def self.map_hash(m)
|
522
|
+
# the keys have to be sorted, otherwise we could be equal
|
523
|
+
# to another map but have a different hashcode.
|
524
|
+
keys = m.keys.sort
|
192
525
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
return Hocon::Impl::SimpleConfigObject.new(origin, updated,
|
198
|
-
ResolveStatus.from_values(updated.values), @ignores_fallbacks)
|
199
|
-
elsif (not remainder.nil?) || v.nil?
|
200
|
-
return self
|
201
|
-
else
|
202
|
-
smaller = Hash.new
|
203
|
-
@value.each do |old_key, old_value|
|
204
|
-
if not old_key == key
|
205
|
-
smaller[old_key] = old_value
|
206
|
-
end
|
207
|
-
end
|
208
|
-
return Hocon::Impl::SimpleConfigObject.new(origin, smaller,
|
209
|
-
ResolveStatus.from_values(smaller.values), @ignores_fallbacks)
|
526
|
+
value_hash = 0
|
527
|
+
|
528
|
+
keys.each do |key|
|
529
|
+
value_hash += m[key].hash
|
210
530
|
end
|
531
|
+
|
532
|
+
41 * (41 + keys.hash) + value_hash
|
211
533
|
end
|
212
534
|
|
213
|
-
def
|
214
|
-
|
215
|
-
|
535
|
+
def can_equal(other)
|
536
|
+
other.is_a? Hocon::ConfigObject
|
537
|
+
end
|
216
538
|
|
217
|
-
|
218
|
-
|
539
|
+
def ==(other)
|
540
|
+
# note that "origin" is deliberately NOT part of equality.
|
541
|
+
# neither are other "extras" like ignoresFallbacks or resolve status.
|
542
|
+
if other.is_a? Hocon::ConfigObject
|
543
|
+
# optimization to avoid unwrapped() for two ConfigObject,
|
544
|
+
# which is what AbstractConfigValue does.
|
545
|
+
can_equal(other) && self.class.map_equals(self, other)
|
219
546
|
else
|
220
|
-
|
221
|
-
if (not child.nil?) && child.is_a?(Hocon::Impl::AbstractConfigObject)
|
222
|
-
return with_value_impl(key, child.with_value(remainder, v))
|
223
|
-
else
|
224
|
-
subtree = v.at_path(
|
225
|
-
SimpleConfigOrigin.new_simple("with_value(#{remainder.render})"), remainder)
|
226
|
-
with_value_impl(key, subtree.root)
|
227
|
-
end
|
547
|
+
false
|
228
548
|
end
|
229
549
|
end
|
230
550
|
|
231
|
-
def
|
232
|
-
|
233
|
-
|
234
|
-
end
|
551
|
+
def hash
|
552
|
+
self.class.map_hash(@value)
|
553
|
+
end
|
235
554
|
|
236
|
-
|
237
|
-
|
238
|
-
|
555
|
+
def contains_key?(key)
|
556
|
+
@value.has_key?(key)
|
557
|
+
end
|
558
|
+
|
559
|
+
def key_set
|
560
|
+
Set.new(@value.keys)
|
561
|
+
end
|
562
|
+
|
563
|
+
def contains_value?(v)
|
564
|
+
@value.has_value?(v)
|
565
|
+
end
|
566
|
+
|
567
|
+
def self.empty(origin = nil)
|
568
|
+
if origin.nil?
|
569
|
+
empty(Hocon::Impl::SimpleConfigOrigin.new_simple("empty config"))
|
239
570
|
else
|
240
|
-
|
241
|
-
new_map[key] = v
|
571
|
+
self.new(origin, {})
|
242
572
|
end
|
243
|
-
self.class.new(origin, new_map, ResolveStatus.from_values(new_map.values), @ignores_fallbacks)
|
244
573
|
end
|
245
|
-
|
574
|
+
|
575
|
+
def self.empty_missing(base_origin)
|
576
|
+
self.new(
|
577
|
+
Hocon::Impl::SimpleConfigOrigin.new_simple("#{base_origin.description} (not found)"),
|
578
|
+
{})
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|