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.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +4 -2
  3. data/lib/hocon.rb +2 -0
  4. data/lib/hocon/config.rb +1010 -0
  5. data/lib/hocon/config_error.rb +32 -2
  6. data/lib/hocon/config_factory.rb +46 -0
  7. data/lib/hocon/config_include_context.rb +49 -0
  8. data/lib/hocon/config_includer_file.rb +27 -0
  9. data/lib/hocon/config_list.rb +49 -0
  10. data/lib/hocon/config_mergeable.rb +74 -0
  11. data/lib/hocon/config_object.rb +144 -1
  12. data/lib/hocon/config_parse_options.rb +33 -9
  13. data/lib/hocon/config_parseable.rb +51 -0
  14. data/lib/hocon/config_render_options.rb +4 -2
  15. data/lib/hocon/config_resolve_options.rb +31 -0
  16. data/lib/hocon/config_syntax.rb +5 -2
  17. data/lib/hocon/config_util.rb +73 -0
  18. data/lib/hocon/config_value.rb +122 -0
  19. data/lib/hocon/config_value_factory.rb +66 -2
  20. data/lib/hocon/config_value_type.rb +5 -2
  21. data/lib/hocon/impl.rb +2 -0
  22. data/lib/hocon/impl/abstract_config_node.rb +29 -0
  23. data/lib/hocon/impl/abstract_config_node_value.rb +11 -0
  24. data/lib/hocon/impl/abstract_config_object.rb +148 -42
  25. data/lib/hocon/impl/abstract_config_value.rb +251 -11
  26. data/lib/hocon/impl/array_iterator.rb +19 -0
  27. data/lib/hocon/impl/config_boolean.rb +7 -1
  28. data/lib/hocon/impl/config_concatenation.rb +177 -28
  29. data/lib/hocon/impl/config_delayed_merge.rb +329 -0
  30. data/lib/hocon/impl/config_delayed_merge_object.rb +274 -0
  31. data/lib/hocon/impl/config_document_parser.rb +647 -0
  32. data/lib/hocon/impl/config_double.rb +44 -0
  33. data/lib/hocon/impl/config_impl.rb +143 -19
  34. data/lib/hocon/impl/config_impl_util.rb +18 -0
  35. data/lib/hocon/impl/config_include_kind.rb +10 -0
  36. data/lib/hocon/impl/config_int.rb +13 -1
  37. data/lib/hocon/impl/config_node_array.rb +11 -0
  38. data/lib/hocon/impl/config_node_comment.rb +19 -0
  39. data/lib/hocon/impl/config_node_complex_value.rb +54 -0
  40. data/lib/hocon/impl/config_node_concatenation.rb +11 -0
  41. data/lib/hocon/impl/config_node_field.rb +81 -0
  42. data/lib/hocon/impl/config_node_include.rb +33 -0
  43. data/lib/hocon/impl/config_node_object.rb +276 -0
  44. data/lib/hocon/impl/config_node_path.rb +48 -0
  45. data/lib/hocon/impl/config_node_root.rb +60 -0
  46. data/lib/hocon/impl/config_node_simple_value.rb +42 -0
  47. data/lib/hocon/impl/config_node_single_token.rb +17 -0
  48. data/lib/hocon/impl/config_null.rb +15 -7
  49. data/lib/hocon/impl/config_number.rb +43 -4
  50. data/lib/hocon/impl/config_parser.rb +403 -0
  51. data/lib/hocon/impl/config_reference.rb +142 -0
  52. data/lib/hocon/impl/config_string.rb +55 -7
  53. data/lib/hocon/impl/container.rb +29 -0
  54. data/lib/hocon/impl/default_transformer.rb +24 -15
  55. data/lib/hocon/impl/from_map_mode.rb +3 -1
  56. data/lib/hocon/impl/full_includer.rb +2 -0
  57. data/lib/hocon/impl/memo_key.rb +42 -0
  58. data/lib/hocon/impl/mergeable_value.rb +8 -0
  59. data/lib/hocon/impl/origin_type.rb +8 -2
  60. data/lib/hocon/impl/parseable.rb +455 -91
  61. data/lib/hocon/impl/path.rb +181 -59
  62. data/lib/hocon/impl/path_builder.rb +24 -3
  63. data/lib/hocon/impl/path_parser.rb +280 -0
  64. data/lib/hocon/impl/replaceable_merge_stack.rb +22 -0
  65. data/lib/hocon/impl/resolve_context.rb +254 -0
  66. data/lib/hocon/impl/resolve_memos.rb +21 -0
  67. data/lib/hocon/impl/resolve_result.rb +39 -0
  68. data/lib/hocon/impl/resolve_source.rb +354 -0
  69. data/lib/hocon/impl/resolve_status.rb +3 -1
  70. data/lib/hocon/impl/simple_config.rb +264 -10
  71. data/lib/hocon/impl/simple_config_document.rb +48 -0
  72. data/lib/hocon/impl/simple_config_list.rb +282 -8
  73. data/lib/hocon/impl/simple_config_object.rb +424 -88
  74. data/lib/hocon/impl/simple_config_origin.rb +263 -71
  75. data/lib/hocon/impl/simple_include_context.rb +31 -1
  76. data/lib/hocon/impl/simple_includer.rb +196 -1
  77. data/lib/hocon/impl/substitution_expression.rb +38 -0
  78. data/lib/hocon/impl/token.rb +17 -4
  79. data/lib/hocon/impl/token_type.rb +6 -2
  80. data/lib/hocon/impl/tokenizer.rb +339 -109
  81. data/lib/hocon/impl/tokens.rb +330 -79
  82. data/lib/hocon/impl/unmergeable.rb +14 -1
  83. data/lib/hocon/impl/unsupported_operation_error.rb +6 -0
  84. data/lib/hocon/impl/url.rb +37 -0
  85. data/lib/hocon/parser.rb +7 -0
  86. data/lib/hocon/parser/config_document.rb +92 -0
  87. data/lib/hocon/parser/config_document_factory.rb +36 -0
  88. data/lib/hocon/parser/config_node.rb +30 -0
  89. metadata +67 -43
  90. data/lib/hocon/impl/config_float.rb +0 -13
  91. data/lib/hocon/impl/parser.rb +0 -977
  92. data/lib/hocon/impl/properties_parser.rb +0 -83
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'hocon/impl'
2
4
 
3
5
  class Hocon::Impl::ResolveStatus
@@ -15,4 +17,4 @@ class Hocon::Impl::ResolveStatus
15
17
  def self.from_boolean(resolved)
16
18
  resolved ? RESOLVED : UNRESOLVED
17
19
  end
18
- end
20
+ end
@@ -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 find_key(me, key, expected, original_path)
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?) ? expected.name : 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.name} " +
43
- "rather than #{expected.name}",
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 has_path(path_expression)
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 => e
73
- raise Hocon::Impl::ConfigImpl.improve_not_resolved(path, e)
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
- end
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 ConfigBugError, "SimpleConfigList created with wrong resolve status: #{self}"
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
- indent(sb, indent_size + 1, options)
39
- sb << "# "
40
- sb << v.origin.description
41
- sb << "\n"
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