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
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ require 'hocon/impl'
4
+ require 'hocon/impl/config_number'
5
+
6
+ class Hocon::Impl::ConfigDouble < Hocon::Impl::ConfigNumber
7
+ def initialize(origin, value, original_text)
8
+ super(origin, original_text)
9
+ @value = value
10
+ end
11
+
12
+ attr_reader :value
13
+
14
+ def value_type
15
+ Hocon::ConfigValueType::NUMBER
16
+ end
17
+
18
+ def unwrapped
19
+ @value
20
+ end
21
+
22
+ def transform_to_string
23
+ s = super
24
+ if s.nil?
25
+ @value.to_s
26
+ else
27
+ s
28
+ end
29
+ end
30
+
31
+ def long_value
32
+ @value.to_i
33
+ end
34
+
35
+ def double_value
36
+ @value
37
+ end
38
+
39
+ def new_copy(origin)
40
+ self.class.new(origin, @value, original_text)
41
+ end
42
+
43
+ # NOTE: skipping `writeReplace` from upstream, because it involves serialization
44
+ end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'hocon/impl'
2
4
  require 'hocon/impl/simple_includer'
3
5
  require 'hocon/config_error'
@@ -6,14 +8,17 @@ require 'hocon/impl/simple_config_origin'
6
8
  require 'hocon/impl/simple_config_list'
7
9
  require 'hocon/impl/config_boolean'
8
10
  require 'hocon/impl/config_null'
11
+ require 'hocon/impl/parseable'
9
12
 
10
13
  class Hocon::Impl::ConfigImpl
11
- @default_includer = Hocon::Impl::SimpleIncluder.new
14
+ @default_includer = Hocon::Impl::SimpleIncluder.new(nil)
12
15
  @default_value_origin = Hocon::Impl::SimpleConfigOrigin.new_simple("hardcoded value")
13
16
  @default_true_value = Hocon::Impl::ConfigBoolean.new(@default_value_origin, true)
14
17
  @default_false_value = Hocon::Impl::ConfigBoolean.new(@default_value_origin, false)
15
18
  @default_null_value = Hocon::Impl::ConfigNull.new(@default_value_origin)
16
19
  @default_empty_list = Hocon::Impl::SimpleConfigList.new(@default_value_origin, Array.new)
20
+ @default_empty_object = Hocon::Impl::SimpleConfigObject.empty(@default_value_origin)
21
+
17
22
 
18
23
  ConfigBugOrBrokenError = Hocon::ConfigError::ConfigBugOrBrokenError
19
24
  ConfigNotResolvedError = Hocon::ConfigError::ConfigNotResolvedError
@@ -23,9 +28,16 @@ class Hocon::Impl::ConfigImpl
23
28
  @default_includer
24
29
  end
25
30
 
31
+
32
+ class FileNameSource < Hocon::Impl::SimpleIncluder::NameSource
33
+ def name_to_parseable(name, parse_options)
34
+ Hocon::Impl::Parseable.new_file(name, parse_options)
35
+ end
36
+ end
37
+
26
38
  def self.improve_not_resolved(what, original)
27
39
  new_message = "#{what.render} has not been resolved, you need to call Config#resolve, see API docs for Config#resolve"
28
- if new_message == original.get_message
40
+ if new_message == original.message
29
41
  return original
30
42
  else
31
43
  return ConfigNotResolvedError.new(new_message, original)
@@ -40,14 +52,11 @@ class Hocon::Impl::ConfigImpl
40
52
  end
41
53
  end
42
54
 
43
- def self.empty_object(origin)
44
- # we want null origin to go to SimpleConfigObject.empty() to get the
45
- # origin "empty config" rather than "hardcoded value"
46
- if origin == @default_value_origin
47
- return default_empty_object
48
- else
49
- return Hocon::Impl::SimpleConfigObject.empty(origin)
50
- end
55
+ def self.parse_file_any_syntax(basename, base_options)
56
+ source = FileNameSource.new()
57
+ Hocon::Impl::SimpleIncluder.from_basename(source,
58
+ File.expand_path(basename),
59
+ base_options)
51
60
  end
52
61
 
53
62
  def self.empty_list(origin)
@@ -65,7 +74,7 @@ class Hocon::Impl::ConfigImpl
65
74
 
66
75
  def self.from_any_ref_mode(object, origin, map_mode)
67
76
  if origin.nil?
68
- raise ConfigBugOrBrokenError.new("origin not supposed to be nil", nil)
77
+ raise ConfigBugOrBrokenError.new("origin not supposed to be nil")
69
78
  end
70
79
  if object.nil?
71
80
  if origin != @default_value_origin
@@ -73,6 +82,8 @@ class Hocon::Impl::ConfigImpl
73
82
  else
74
83
  return @default_null_value
75
84
  end
85
+ elsif object.is_a?(Hocon::Impl::AbstractConfigValue)
86
+ return object
76
87
  elsif object.is_a?(TrueClass) || object.is_a?(FalseClass)
77
88
  if origin != @default_value_origin
78
89
  return Hocon::Impl::ConfigBoolean.new(origin, object)
@@ -82,7 +93,7 @@ class Hocon::Impl::ConfigImpl
82
93
  return @default_false_value
83
94
  end
84
95
  elsif object.is_a?(String)
85
- return Hocon::Impl::ConfigString.new(origin, object)
96
+ return Hocon::Impl::ConfigString::Quoted.new(origin, object)
86
97
  elsif object.is_a?(Numeric)
87
98
  # here we always keep the same type that was passed to us,
88
99
  # rather than figuring out if a Long would fit in an Int
@@ -90,7 +101,7 @@ class Hocon::Impl::ConfigImpl
90
101
  # not using ConfigNumber.newNumber() when we have a
91
102
  # Double, Integer, or Long.
92
103
  if object.is_a?(Float)
93
- return Hocon::Impl::ConfigFloat.new(origin, object, nil)
104
+ return Hocon::Impl::ConfigDouble.new(origin, object, nil)
94
105
  elsif object.is_a?(Integer)
95
106
  return Hocon::Impl::ConfigInt.new(origin, object, nil)
96
107
  else
@@ -98,7 +109,7 @@ class Hocon::Impl::ConfigImpl
98
109
  end
99
110
  elsif object.is_a?(Hash)
100
111
  if object.empty?
101
- return self.empty_object(origin)
112
+ return self.empty_object_from_origin(origin)
102
113
  end
103
114
 
104
115
  if map_mode == FromMapMode::KEYS_ARE_KEYS
@@ -106,15 +117,14 @@ class Hocon::Impl::ConfigImpl
106
117
  object.each do |key, entry|
107
118
  if not key.is_a?(String)
108
119
  raise ConfigBugOrBrokenError.new(
109
- "bug in method caller: not valid to create ConfigObject from map with non-String key: #{key}",
110
- nil)
120
+ "bug in method caller: not valid to create ConfigObject from map with non-String key: #{key}")
111
121
  end
112
122
  value = self.from_any_ref_mode(entry, origin, map_mode)
113
123
  values[key] = value
114
124
  end
115
125
  return Hocon::Impl::SimpleConfigObject.new(origin, values)
116
126
  else
117
- return Hocon::Impl::PropertiesParser.from_path_map(origin, object)
127
+ raise ConfigBugOrBrokenError, "java properties format not supported"
118
128
  end
119
129
  elsif object.is_a?(Enumerable)
120
130
  if object.count == 0
@@ -129,7 +139,121 @@ class Hocon::Impl::ConfigImpl
129
139
 
130
140
  return Hocon::Impl::SimpleConfigList.new(origin, values)
131
141
  else
132
- raise ConfigBugOrBrokenError.new("bug in method caller: not valid to create ConfigValue from: #{object}", nil)
142
+ raise ConfigBugOrBrokenError.new("bug in method caller: not valid to create ConfigValue from: #{object}")
143
+ end
144
+ end
145
+
146
+
147
+
148
+ def self.env_variables_as_config_object
149
+ EnvVariablesHolder.get_env_variables
150
+ end
151
+
152
+ # This class is a lot simpler than the Java version ...
153
+ # The Java version uses system properties to toggle these settings.
154
+ # We don't have system properties in MRI so it's not clear what to do here.
155
+ # Initially, I ported this as more of a direct translation from the Java code,
156
+ # but I ran into issues around how to translate stupid Java static
157
+ # initialization crap to Ruby, so what we have here is a much simpler version
158
+ # that is # equivalent.
159
+ #
160
+ # There's no way to toggle this logging without changing code, but it's
161
+ # actually proved to be useful for debugging purposes while porting code
162
+ # down from Java.
163
+ class DebugHolder
164
+ class << self
165
+
166
+ def trace_loads_enabled
167
+ TRACE_LOADS_ENABLED
168
+ end
169
+
170
+ def trace_substitutions_enabled
171
+ TRACE_SUBSTITUTIONS_ENABLED
172
+ end
173
+
174
+ private
175
+
176
+ TRACE_LOADS_ENABLED = false
177
+ TRACE_SUBSTITUTIONS_ENABLED = false
178
+ end
179
+ end
180
+
181
+ def self.trace_loads_enabled
182
+ # Ignoring 'catch ExceptionInInitializerError' from that java version,
183
+ # that is just terrible java code anyway.
184
+ DebugHolder.trace_loads_enabled
185
+ end
186
+
187
+ def self.trace_substitution_enabled
188
+ # Ignoring 'catch ExceptionInInitializerError' from that java version,
189
+ # that is just terrible java code anyway.
190
+ DebugHolder.trace_substitutions_enabled
191
+ end
192
+
193
+ def self.trace(message, indent_level = 0)
194
+ while indent_level > 0
195
+ $stderr.putc(" ")
196
+ indent_level -= 1
197
+ end
198
+ $stderr.puts(message)
199
+ end
200
+
201
+ def self.empty_object_from_origin(origin)
202
+ # we want null origin to go to SimpleConfigObject.empty() to get the
203
+ # origin "empty config" rather than "hardcoded value"
204
+ if origin == @default_value_origin
205
+ @default_empty_object
206
+ else
207
+ Hocon::Impl::SimpleConfigObject.empty(origin)
208
+ end
209
+ end
210
+
211
+ def self.empty_object(origin_description)
212
+ if !origin_description.nil?
213
+ origin = Hocon::Impl::SimpleConfigOrigin.new_simple(origin_description)
214
+ else
215
+ origin = nil
216
+ end
217
+
218
+ empty_object_from_origin(origin)
219
+ end
220
+
221
+ def self.empty_config(origin_description)
222
+ empty_object(origin_description).to_config
223
+ end
224
+
225
+ def empty(origin)
226
+ self.class.empty_object_from_origin(origin)
227
+ end
228
+
229
+ def self.default_reference
230
+ resource = Hocon::Impl::Parseable.new_resources("reference.conf",
231
+ Hocon::ConfigParseOptions.defaults)
232
+ resource.parse.to_config
233
+ end
234
+
235
+ private
236
+
237
+ def self.load_env_variables
238
+ env = ENV
239
+ m = {}
240
+ env.each do |key, value|
241
+ m[key] = Hocon::Impl::ConfigString::Quoted.new(
242
+ Hocon::Impl::SimpleConfigOrigin.new_simple("env var #{key}"), value)
243
+ end
244
+
245
+ Hocon::Impl::SimpleConfigObject.new(
246
+ Hocon::Impl::SimpleConfigOrigin.new_simple("env variables"),
247
+ m,
248
+ Hocon::Impl::ResolveStatus::RESOLVED,
249
+ false)
250
+ end
251
+
252
+ class EnvVariablesHolder
253
+ ENV_VARIABLES = Hocon::Impl::ConfigImpl.load_env_variables
254
+
255
+ def self.get_env_variables
256
+ ENV_VARIABLES
133
257
  end
134
258
  end
135
- end
259
+ end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'hocon/impl'
2
4
  require 'stringio'
3
5
 
@@ -68,6 +70,22 @@ class Hocon::Impl::ConfigImplUtil
68
70
  s
69
71
  end
70
72
 
73
+ def self.join_path(*elements)
74
+ Hocon::Impl::Path.from_string_list(elements).render
75
+ end
76
+
77
+ def self.split_path(path)
78
+ p = Hocon::Impl::Path.new_path(path)
79
+ elements = []
80
+
81
+ until p.nil?
82
+ elements << p.first
83
+ p = p.remainder
84
+ end
85
+
86
+ elements
87
+ end
88
+
71
89
  def self.whitespace?(c)
72
90
  # this implementation is *not* a port of the java code, because it relied on
73
91
  # the method java.lang.Character#isWhitespace. This is probably
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ require 'hocon/impl'
4
+
5
+ module Hocon::Impl::ConfigIncludeKind
6
+ URL = 0
7
+ FILE = 1
8
+ CLASSPATH = 2
9
+ HEURISTIC = 3
10
+ end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'hocon/impl'
2
4
  require 'hocon/impl/config_number'
3
5
  require 'hocon/config_value_type'
@@ -8,6 +10,8 @@ class Hocon::Impl::ConfigInt < Hocon::Impl::ConfigNumber
8
10
  @value = value
9
11
  end
10
12
 
13
+ attr_reader :value
14
+
11
15
  def value_type
12
16
  Hocon::ConfigValueType::NUMBER
13
17
  end
@@ -25,7 +29,15 @@ class Hocon::Impl::ConfigInt < Hocon::Impl::ConfigNumber
25
29
  end
26
30
  end
27
31
 
32
+ def long_value
33
+ @value
34
+ end
35
+
36
+ def double_value
37
+ @value
38
+ end
39
+
28
40
  def new_copy(origin)
29
41
  Hocon::Impl::ConfigInt.new(origin, @value, @original_text)
30
42
  end
31
- end
43
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ require 'hocon/impl'
4
+ require 'hocon/impl/config_node_complex_value'
5
+
6
+ class Hocon::Impl::ConfigNodeArray
7
+ include Hocon::Impl::ConfigNodeComplexValue
8
+ def new_node(nodes)
9
+ self.class.new(nodes)
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'hocon/impl'
4
+ require 'hocon/config_error'
5
+ require 'hocon/impl/config_node_single_token'
6
+ require 'hocon/impl/tokens'
7
+
8
+ class Hocon::Impl::ConfigNodeComment < Hocon::Impl::ConfigNodeSingleToken
9
+ def initialize(comment)
10
+ super(comment)
11
+ unless Hocon::Impl::Tokens.comment?(@token)
12
+ raise Hocon::ConfigError::ConfigBugOrBrokenError, 'Tried to create a ConfigNodeComment from a non-comment token'
13
+ end
14
+ end
15
+
16
+ def comment_text
17
+ Hocon::Impl::Tokens.comment_text(@token)
18
+ end
19
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ require 'hocon/impl'
4
+ require 'hocon/impl/abstract_config_node_value'
5
+ require 'hocon/impl/config_node_field'
6
+ require 'hocon/impl/config_node_include'
7
+ require 'hocon/impl/config_node_single_token'
8
+ require 'hocon/impl/tokens'
9
+ require 'hocon/config_error'
10
+
11
+ module Hocon::Impl::ConfigNodeComplexValue
12
+ include Hocon::Impl::AbstractConfigNodeValue
13
+ def initialize(children)
14
+ @children = children
15
+ end
16
+
17
+ attr_reader :children
18
+
19
+ def tokens
20
+ tokens = []
21
+ @children.each do |child|
22
+ tokens += child.tokens
23
+ end
24
+ tokens
25
+ end
26
+
27
+ def indent_text(indentation)
28
+ children_copy = @children.clone
29
+ i = 0
30
+ while i < children_copy.size
31
+ child = children_copy[i]
32
+ if child.is_a?(Hocon::Impl::ConfigNodeSingleToken) && Hocon::Impl::Tokens.newline?(child.token)
33
+ children_copy.insert(i + 1, indentation)
34
+ i += 1
35
+ elsif child.is_a?(Hocon::Impl::ConfigNodeField)
36
+ value = child.value
37
+ if value.is_a?(Hocon::Impl::ConfigNodeComplexValue)
38
+ children_copy[i] = child.replace_value(value.indent_text(indentation))
39
+ end
40
+ elsif child.is_a?(Hocon::Impl::ConfigNodeComplexValue)
41
+ children_copy[i] = child.indent_text(indentation)
42
+ end
43
+ i += 1
44
+ end
45
+ new_node(children_copy)
46
+ end
47
+
48
+ # This method will just call into the object's constructor, but it's needed
49
+ # for use in the indentText() method so we can avoid a gross if/else statement
50
+ # checking the type of this
51
+ def new_node(nodes)
52
+ raise Hocon::ConfigError::ConfigBugOrBrokenError, "subclasses of ConfigNodeComplexValue should override `new_node` (#{self.class})"
53
+ end
54
+ end