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,24 +1,200 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'uri'
2
4
  require 'hocon/impl'
5
+ require 'hocon/impl/url'
3
6
  require 'hocon/impl/origin_type'
7
+ require 'hocon/config_error'
4
8
 
5
9
  class Hocon::Impl::SimpleConfigOrigin
6
10
 
7
- MERGE_OF_PREFIX = "merge of "
11
+ OriginType = Hocon::Impl::OriginType
12
+
13
+ def initialize(description, line_number, end_line_number,
14
+ origin_type, url_or_nil, resource_or_nil, comments_or_nil)
15
+ if !description
16
+ raise ArgumentError, "description may not be nil"
17
+ end
18
+
19
+ # HACK: naming this variable with an underscore, because the upstream library
20
+ # has both a member var and a no-arg method by the name "description", and
21
+ # I don't think Ruby can handle that.
22
+ @_description = description
23
+ @line_number = line_number
24
+ @end_line_number = end_line_number
25
+ @origin_type = origin_type
26
+ @url_or_nil = url_or_nil
27
+ @resource_or_nil = resource_or_nil
28
+ @comments_or_nil = comments_or_nil
29
+ end
30
+
31
+ attr_reader :_description, :line_number, :end_line_number, :origin_type,
32
+ :url_or_nil, :resource_or_nil, :comments_or_nil
33
+
34
+
35
+ def self.new_simple(description)
36
+ self.new(description, -1, -1,
37
+ OriginType::GENERIC,
38
+ nil, nil, nil)
39
+ end
8
40
 
9
41
  def self.new_file(file_path)
10
42
  url = URI.join('file:///', file_path)
11
43
  self.new(file_path, -1, -1,
12
- Hocon::Impl::OriginType::FILE,
13
- url, nil)
44
+ OriginType::FILE,
45
+ url, nil, nil)
14
46
  end
15
47
 
16
- def self.new_simple(description)
17
- self.new(description, -1, -1,
18
- Hocon::Impl::OriginType::GENERIC,
19
- nil, nil)
48
+ # NOTE: not porting `new_url` because we're not going to support URLs for now
49
+
50
+ def self.new_resource(resource, url = nil)
51
+ desc = nil
52
+ if ! url.nil?
53
+ desc = resource + " @ " + url.to_external_form
54
+ else
55
+ desc = resource
56
+ end
57
+ Hocon::Impl::SimpleConfigOrigin.new(desc, -1, -1, OriginType::RESOURCE,
58
+ url.nil? ? nil : url.to_external_form,
59
+ resource, nil)
20
60
  end
21
61
 
62
+ def with_line_number(line_number)
63
+ if (line_number == @line_number) and
64
+ (line_number == @end_line_number)
65
+ self
66
+ else
67
+ Hocon::Impl::SimpleConfigOrigin.new(
68
+ @_description, line_number, line_number,
69
+ @origin_type, @url_or_nil, @resource_or_nil, @comments_or_nil)
70
+ end
71
+ end
72
+
73
+ def add_url(url)
74
+ SimpleConfigOrigin.new(@_description, line_number, end_line_number, origin_type,
75
+ url.nil? ? nil : url.to_s, resource_or_nil,
76
+ comments_or_nil)
77
+ end
78
+
79
+ def with_comments(comments)
80
+ if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(comments, @comments_or_nil)
81
+ self
82
+ else
83
+ Hocon::Impl::SimpleConfigOrigin.new(
84
+ @_description, @line_number, @end_line_number,
85
+ @origin_type, @url_or_nil, @resource_or_nil, comments)
86
+ end
87
+ end
88
+
89
+ def prepend_comments(comments)
90
+ if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(comments, @comments_or_nil)
91
+ self
92
+ elsif @comments_or_nil.nil?
93
+ with_comments(comments)
94
+ else
95
+ merged = comments + @comments_or_nil
96
+ with_comments(merged)
97
+ end
98
+ end
99
+
100
+ def append_comments(comments)
101
+ if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(comments, @comments_or_nil)
102
+ self
103
+ elsif comments_or_nil.nil?
104
+ with_comments(comments)
105
+ else
106
+ merged = comments_or_nil + comments
107
+ with_comments(merged)
108
+ end
109
+ end
110
+
111
+ def description
112
+ if @line_number < 0
113
+ _description
114
+ elsif end_line_number == line_number
115
+ "#{_description}: #{line_number}"
116
+ else
117
+ "#{_description}: #{line_number}-#{end_line_number}"
118
+ end
119
+ end
120
+
121
+ def ==(other)
122
+ if other.is_a? Hocon::Impl::SimpleConfigOrigin
123
+ @_description == other._description &&
124
+ @line_number == other.line_number &&
125
+ @end_line_number == other.end_line_number &&
126
+ @origin_type == other.origin_type &&
127
+ Hocon::Impl::ConfigImplUtil.equals_handling_nil?(@url_or_nil, other.url_or_nil) &&
128
+ Hocon::Impl::ConfigImplUtil.equals_handling_nil?(@resource_or_nil, other.resource_or_nil)
129
+ else
130
+ false
131
+ end
132
+ end
133
+
134
+ def hash
135
+ h = 41 * (41 + @_description.hash)
136
+ h = 41 * (h + @line_number)
137
+ h = 41 * (h + @end_line_number)
138
+ h = 41 * (h + @origin_type.hash)
139
+
140
+ unless @url_or_nil.nil?
141
+ h = 41 * (h + @url_or_nil.hash)
142
+ end
143
+
144
+ unless @resource_or_nil.nil?
145
+ h = 41 * (h + @resource_or_nil.hash)
146
+ end
147
+
148
+ h
149
+ end
150
+
151
+ def to_s
152
+ "ConfigOrigin(#{_description})"
153
+ end
154
+
155
+ def filename
156
+ if origin_type == OriginType::FILE
157
+ _description
158
+ elsif ! url_or_nil.nil?
159
+ url = nil
160
+ begin
161
+ url = Hocon::Impl::Url.new(url_or_nil)
162
+ rescue Hocon::Impl::Url::MalformedUrlError => e
163
+ return nil
164
+ end
165
+
166
+ if url.get_protocol == "file"
167
+ url.get_file
168
+ else
169
+ nil
170
+ end
171
+ else
172
+ nil
173
+ end
174
+ end
175
+
176
+ def url
177
+ if url_or_nil.nil?
178
+ nil
179
+ else
180
+ begin
181
+ Hocon::Impl::Url.new(url_or_nil)
182
+ rescue Hocon::Impl::Url::MalformedUrlError => e
183
+ nil
184
+ end
185
+ end
186
+ end
187
+
188
+ def resource
189
+ resource_or_nil
190
+ end
191
+
192
+ def comments
193
+ @comments_or_nil || []
194
+ end
195
+
196
+ MERGE_OF_PREFIX = "merge of "
197
+
22
198
  def self.remove_merge_of_prefix(desc)
23
199
  if desc.start_with?(MERGE_OF_PREFIX)
24
200
  desc = desc[MERGE_OF_PREFIX.length, desc.length - 1]
@@ -41,8 +217,8 @@ class Hocon::Impl::SimpleConfigOrigin
41
217
 
42
218
  # first use the "description" field which has no line numbers
43
219
  # cluttering it.
44
- a_desc = remove_merge_of_prefix(a.description)
45
- b_desc = remove_merge_of_prefix(b.description)
220
+ a_desc = remove_merge_of_prefix(a._description)
221
+ b_desc = remove_merge_of_prefix(b._description)
46
222
 
47
223
  if a_desc == b_desc
48
224
  merged_desc = a_desc
@@ -62,8 +238,8 @@ class Hocon::Impl::SimpleConfigOrigin
62
238
  #
63
239
  # description() method includes line numbers, so use it instead
64
240
  # of description field.
65
- a_full = remove_merge_of_prefix(a.description)
66
- b_full = remove_merge_of_prefix(b.description)
241
+ a_full = remove_merge_of_prefix(a._description)
242
+ b_full = remove_merge_of_prefix(b._description)
67
243
 
68
244
  merged_desc = "#{MERGE_OF_PREFIX}#{a_full},#{b_full}"
69
245
  merged_start_line = -1
@@ -77,6 +253,13 @@ class Hocon::Impl::SimpleConfigOrigin
77
253
  nil
78
254
  end
79
255
 
256
+ merged_resource =
257
+ if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(a.resource_or_nil, b.resource_or_nil)
258
+ a.resource_or_nil
259
+ else
260
+ nil
261
+ end
262
+
80
263
  if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(a.comments_or_nil, b.comments_or_nil)
81
264
  merged_comments = a.comments_or_nil
82
265
  else
@@ -91,84 +274,93 @@ class Hocon::Impl::SimpleConfigOrigin
91
274
 
92
275
  Hocon::Impl::SimpleConfigOrigin.new(
93
276
  merged_desc, merged_start_line, merged_end_line,
94
- merged_type, merged_url, merged_comments)
277
+ merged_type, merged_url, merged_resource, merged_comments)
95
278
  end
96
279
 
97
- def self.merge_origins(stack)
98
- if stack.empty?
99
- raise ConfigBugError, "can't merge empty list of origins"
100
- elsif stack.length == 1
101
- stack[0]
102
- elsif stack.length == 2
103
- merge_two(stack[0], stack[1])
104
- else
105
- remaining = stack.clone
106
- while remaining.length > 2
107
- merged = merge_three(remaining[0], remaining[1], remaining[2])
108
- remaining.pop
109
- remaining.pop
110
- remaining.pop
280
+ def self.similarity(a, b)
281
+ count = 0
282
+ if a.origin_type == b.origin_type
283
+ count += 1
284
+ end
285
+
286
+ if a._description == b._description
287
+ count += 1
288
+
289
+ # only count these if the description field (which is the file
290
+ # or resource name) also matches.
291
+ if a.line_number == b.line_number
292
+ count += 1
111
293
  end
112
294
 
113
- # should be down to either 1 or 2
114
- merge_origins(remaining)
115
- end
116
- end
295
+ if a.end_line_number == b.end_line_number
296
+ count += 1
297
+ end
117
298
 
299
+ if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(a.url_or_nil, b.url_or_nil)
300
+ count += 1
301
+ end
118
302
 
119
- def initialize(description, line_number, end_line_number,
120
- origin_type, url, comments)
121
- if !description
122
- raise ArgumentError, "description may not be nil"
303
+ if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(a.resource_or_nil, b.resource_or_nil)
304
+ count += 1
305
+ end
123
306
  end
124
307
 
125
- @description = description
126
- @line_number = line_number
127
- @end_line_number = end_line_number
128
- @origin_type = origin_type
129
- @url_or_nil = url
130
- @comments_or_nil = comments
308
+ count
131
309
  end
132
310
 
133
- attr_reader :description, :line_number, :end_line_number, :origin_type,
134
- :url_or_nil, :comments_or_nil
135
-
136
- def set_line_number(line_number)
137
- if (line_number == @line_number) and
138
- (line_number == @end_line_number)
139
- self
311
+ def self.merge_three(a, b, c)
312
+ if similarity(a, b) >= similarity(b, c)
313
+ merge_two(merge_two(a, b), c)
140
314
  else
141
- Hocon::Impl::SimpleConfigOrigin.new(
142
- @description, line_number, line_number,
143
- @origin_type, @url_or_nil, @comments_or_nil)
315
+ merge_two(a, merge_two(b, c))
144
316
  end
145
317
  end
146
318
 
147
- def set_comments(comments)
148
- if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(comments, @comments_or_nil)
149
- self
150
- else
151
- Hocon::Impl::SimpleConfigOrigin.new(
152
- @description, @line_number, @end_line_number,
153
- @origin_type, @url_or_nil, comments)
154
- end
319
+ def self.merge_two_origins(a, b)
320
+ # a, b are ConfigOrigins
321
+ merge_two(a, b)
155
322
  end
156
323
 
157
- def prepend_comments(comments)
158
- if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(comments, @comments_or_nil)
159
- self
160
- elsif @comments_or_nil.nil?
161
- set_comments(comments)
324
+ def self.merge_value_origins(stack)
325
+ # stack is an array of AbstractConfigValue
326
+ origins = stack.map { |v| v.origin}
327
+ merge_origins(origins)
328
+ end
329
+
330
+ # see also 'merge_two_origins' and 'merge_three_origins'
331
+ def self.merge_origins(stack)
332
+ # stack is an array of ConfigOrigin
333
+ if stack.empty?
334
+ raise Hocon::ConfigError::ConfigBugOrBrokenError, "can't merge empty list of origins"
335
+ elsif stack.length == 1
336
+ stack[0]
337
+ elsif stack.length == 2
338
+ merge_two(stack[0], stack[1])
162
339
  else
163
- merged = []
164
- merged.concat(comments)
165
- merged.concat(@comments_or_nil)
166
- set_comments(merged)
340
+ remaining = []
341
+ stack.each do |o|
342
+ remaining << o
343
+ end
344
+ while remaining.size > 2
345
+ c = remaining.last
346
+ remaining.delete_at(remaining.size - 1)
347
+ b = remaining.last
348
+ remaining.delete_at(remaining.size - 1)
349
+ a = remaining.last
350
+ remaining.delete_at(remaining.size - 1)
351
+
352
+ merged = merge_three(a, b, c)
353
+
354
+ remaining << merged
355
+ end
356
+
357
+ # should be down to either 1 or 2
358
+ self.merge_origins(remaining)
167
359
  end
168
360
  end
169
361
 
170
- def comments
171
- @comments_or_nil || []
172
- end
362
+ # NOTE: skipping 'toFields', 'toFieldsDelta', 'fieldsDelta', 'fromFields',
363
+ # 'applyFieldsDelta', and 'fromBase' from upstream for now, because they appear
364
+ # to be about serialization and we probably won't be supporting that.
173
365
 
174
- end
366
+ end
@@ -1,7 +1,37 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'hocon/impl'
4
+ require 'hocon/impl/simple_includer'
5
+ require 'hocon/config_include_context'
6
+ require 'hocon/impl/config_impl'
2
7
 
3
8
  class Hocon::Impl::SimpleIncludeContext
9
+ include Hocon::ConfigIncludeContext
10
+
4
11
  def initialize(parseable)
5
12
  @parseable = parseable
6
13
  end
7
- end
14
+
15
+ def with_parseable(parseable)
16
+ if parseable.equal?(@parseable)
17
+ self
18
+ else
19
+ self.class.new(parseable)
20
+ end
21
+ end
22
+
23
+ def relative_to(filename)
24
+ if Hocon::Impl::ConfigImpl.trace_loads_enabled
25
+ Hocon::Impl::ConfigImpl.trace("Looking for '#{filename}' relative to #{@parseable}")
26
+ end
27
+ if ! @parseable.nil?
28
+ @parseable.relative_to(filename)
29
+ else
30
+ nil
31
+ end
32
+ end
33
+
34
+ def parse_options
35
+ Hocon::Impl::SimpleIncluder.clear_for_include(@parseable.options)
36
+ end
37
+ end
@@ -1,7 +1,202 @@
1
+ # encoding: utf-8
2
+
3
+ require 'stringio'
1
4
  require 'hocon/impl'
2
5
  require 'hocon/impl/full_includer'
6
+ require 'hocon/impl/url'
7
+ require 'hocon/impl/config_impl'
8
+ require 'hocon/config_error'
9
+ require 'hocon/config_syntax'
10
+ require 'hocon/impl/simple_config_object'
11
+ require 'hocon/impl/simple_config_origin'
12
+ require 'hocon/config_includer_file'
13
+ require 'hocon/config_factory'
14
+ require 'hocon/impl/parseable'
3
15
 
4
16
  class Hocon::Impl::SimpleIncluder < Hocon::Impl::FullIncluder
17
+
18
+ ConfigBugorBrokenError = Hocon::ConfigError::ConfigBugOrBrokenError
19
+ ConfigIOError = Hocon::ConfigError::ConfigIOError
20
+ SimpleConfigObject = Hocon::Impl::SimpleConfigObject
21
+ SimpleConfigOrigin = Hocon::Impl::SimpleConfigOrigin
22
+
23
+
24
+ def initialize(fallback)
25
+ @fallback = fallback
26
+ end
27
+
28
+ # ConfigIncludeContext does this for us on its options
29
+ def self.clear_for_include(options)
30
+ # the class loader and includer are inherited, but not this other stuff
31
+ options.set_syntax(nil).set_origin_description(nil).set_allow_missing(true)
32
+ end
33
+
34
+
35
+ # this is the heuristic includer
36
+ def include(context, name)
37
+ obj = self.class.include_without_fallback(context, name)
38
+
39
+ # now use the fallback includer if any and merge its result
40
+ if ! (@fallback.nil?)
41
+ obj.with_fallback(@fallback.include(context, name))
42
+ else
43
+ obj
44
+ end
45
+ end
46
+
47
+ # the heuristic includer in static form
48
+ def self.include_without_fallback(context, name)
49
+ # the heuristic is valid URL then URL, else relative to including file;
50
+ # relativeTo in a file falls back to classpath inside relativeTo().
51
+
52
+ url = nil
53
+ begin
54
+ url = Hocon::Impl::Url.new(name)
55
+ rescue Hocon::Impl::Url::MalformedUrlError => e
56
+ url = nil
57
+ end
58
+
59
+ if !(url.nil?)
60
+ include_url_without_fallback(context, url)
61
+ else
62
+ source = RelativeNameSource.new(context)
63
+ from_basename(source, name, context.parse_options)
64
+ end
65
+ end
66
+
67
+ # NOTE: not porting `include_url` or `include_url_without_fallback` from upstream,
68
+ # because we probably won't support URL includes for now.
69
+
70
+ def include_file(context, file)
71
+ obj = self.class.include_file_without_fallback(context, file)
72
+
73
+ # now use the fallback includer if any and merge its result
74
+ if (!@fallback.nil?) && @fallback.is_a?(Hocon::ConfigIncluderFile)
75
+ obj.with_fallback(@fallback).include_file(context, file)
76
+ else
77
+ obj
78
+ end
79
+ end
80
+
81
+ def self.include_file_without_fallback(context, file)
82
+ Hocon::ConfigFactory.parse_file_any_syntax(file, context.parse_options).root
83
+ end
84
+
85
+ # NOTE: not porting `include_resources` or `include_resources_without_fallback`
86
+ # for now because we're not going to support looking for things on the ruby
87
+ # load path for now.
88
+
89
+ def with_fallback(fallback)
90
+ if self.equal?(fallback)
91
+ raise ConfigBugOrBrokenError, "trying to create includer cycle"
92
+ elsif @fallback.equal?(fallback)
93
+ self
94
+ elsif @fallback.nil?
95
+ self.class.new(@fallback.with_fallback(fallback))
96
+ else
97
+ self.class.new(fallback)
98
+ end
99
+ end
100
+
101
+
102
+ class NameSource
103
+ def name_to_parseable(name, parse_options)
104
+ raise Hocon::ConfigError::ConfigBugOrBrokenError,
105
+ "name_to_parseable must be implemented by subclass (#{self.class})"
106
+ end
107
+ end
108
+
109
+ class RelativeNameSource < NameSource
110
+ def initialize(context)
111
+ @context = context
112
+ end
113
+
114
+ def name_to_parseable(name, options)
115
+ p = @context.relative_to(name)
116
+ if p.nil?
117
+ # avoid returning nil
118
+ Hocon::Impl::Parseable.new_not_found(name, "include was not found: '#{name}'", options)
119
+ else
120
+ p
121
+ end
122
+ end
123
+ end
124
+
125
+ # this function is a little tricky because there are three places we're
126
+ # trying to use it; for 'include "basename"' in a .conf file, for
127
+ # loading app.{conf,json,properties} from classpath, and for
128
+ # loading app.{conf,json,properties} from the filesystem.
129
+ def self.from_basename(source, name, options)
130
+ obj = nil
131
+ if name.end_with?(".conf") || name.end_with?(".json") || name.end_with?(".properties")
132
+ p = source.name_to_parseable(name, options)
133
+
134
+ obj = p.parse(p.options.set_allow_missing(options.allow_missing?))
135
+ else
136
+ conf_handle = source.name_to_parseable(name + ".conf", options)
137
+ json_handle = source.name_to_parseable(name + ".json", options)
138
+ got_something = false
139
+ fails = []
140
+
141
+ syntax = options.syntax
142
+
143
+ obj = SimpleConfigObject.empty(SimpleConfigOrigin.new_simple(name))
144
+ if syntax.nil? || (syntax == Hocon::ConfigSyntax::CONF)
145
+ begin
146
+ obj = conf_handle.parse(conf_handle.options.set_allow_missing(false).
147
+ set_syntax(Hocon::ConfigSyntax::CONF))
148
+ got_something = true
149
+ rescue ConfigIOError => e
150
+ fails << e
151
+ end
152
+ end
153
+
154
+ if syntax.nil? || (syntax == Hocon::ConfigSyntax::JSON)
155
+ begin
156
+ parsed = json_handle.parse(json_handle.options.set_allow_missing(false).
157
+ set_syntax(Hocon::ConfigSyntax::JSON))
158
+ obj = obj.with_fallback(parsed)
159
+ got_something = true
160
+ rescue ConfigIOError => e
161
+ fails << e
162
+ end
163
+ end
164
+
165
+ # NOTE: skipping the upstream block here that would attempt to parse
166
+ # a java properties file.
167
+
168
+ if (! options.allow_missing?) && (! got_something)
169
+ if Hocon::Impl::ConfigImpl.trace_loads_enabled
170
+ # the individual exceptions should have been logged already
171
+ # with tracing enabled
172
+ Hocon::Impl::ConfigImpl.trace("Did not find '#{name}'" +
173
+ " with any extension (.conf, .json, .properties); " +
174
+ "exceptions should have been logged above.")
175
+ end
176
+
177
+ if fails.empty?
178
+ # this should not happen
179
+ raise ConfigBugOrBrokenError, "should not be reached: nothing found but no exceptions thrown"
180
+ else
181
+ sb = StringIO.new
182
+ fails.each do |t|
183
+ sb << t
184
+ sb << ", "
185
+ end
186
+ raise ConfigIOError.new(SimpleConfigOrigin.new_simple(name), sb.string, fails[0])
187
+ end
188
+ elsif !got_something
189
+ if Hocon::Impl::ConfigImpl.trace_loads_enabled
190
+ Hocon::Impl::ConfigImpl.trace("Did not find '#{name}'" +
191
+ " with any extension (.conf, .json, .properties); but '#{name}'" +
192
+ " is allowed to be missing. Exceptions from load attempts should have been logged above.")
193
+ end
194
+ end
195
+ end
196
+
197
+ obj
198
+ end
199
+
5
200
  class Proxy < Hocon::Impl::FullIncluder
6
201
  def initialize(delegate)
7
202
  @delegate = delegate
@@ -16,4 +211,4 @@ class Hocon::Impl::SimpleIncluder < Hocon::Impl::FullIncluder
16
211
  Proxy.new(includer)
17
212
  end
18
213
  end
19
- end
214
+ end