hocon 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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