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,44 +1,79 @@
1
+ # encoding: utf-8
2
+
3
+ require 'stringio'
1
4
  require 'hocon/impl'
2
5
  require 'hocon/impl/token'
3
6
  require 'hocon/impl/token_type'
4
7
  require 'hocon/impl/config_number'
5
8
  require 'hocon/impl/config_string'
9
+ require 'hocon/impl/config_null'
6
10
  require 'hocon/impl/config_boolean'
7
11
  require 'hocon/config_error'
12
+ require 'hocon/impl/resolve_status'
8
13
 
9
14
  # FIXME the way the subclasses of Token are private with static isFoo and accessors is kind of ridiculous.
10
15
  class Hocon::Impl::Tokens
11
16
  Token = Hocon::Impl::Token
12
17
  TokenType = Hocon::Impl::TokenType
13
18
  ConfigNumber = Hocon::Impl::ConfigNumber
19
+ ConfigInt = Hocon::Impl::ConfigInt
20
+ ConfigDouble = Hocon::Impl::ConfigDouble
14
21
  ConfigString = Hocon::Impl::ConfigString
22
+ ConfigNull = Hocon::Impl::ConfigNull
15
23
  ConfigBoolean = Hocon::Impl::ConfigBoolean
24
+ ResolveStatus = Hocon::Impl::ResolveStatus
16
25
 
17
- START = Token.new_without_origin(TokenType::START, "start of file")
18
- EOF = Token.new_without_origin(TokenType::EOF, "end of file")
19
- COMMA = Token.new_without_origin(TokenType::COMMA, "','")
20
- EQUALS = Token.new_without_origin(TokenType::EQUALS, "'='")
21
- COLON = Token.new_without_origin(TokenType::COLON, "':'")
22
- OPEN_CURLY = Token.new_without_origin(TokenType::OPEN_CURLY, "'{'")
23
- CLOSE_CURLY = Token.new_without_origin(TokenType::CLOSE_CURLY, "'}'")
24
- OPEN_SQUARE = Token.new_without_origin(TokenType::OPEN_SQUARE, "'['")
25
- CLOSE_SQUARE = Token.new_without_origin(TokenType::CLOSE_SQUARE, "']'")
26
- PLUS_EQUALS = Token.new_without_origin(TokenType::PLUS_EQUALS, "'+='")
26
+ ConfigBugOrBrokenError = Hocon::ConfigError::ConfigBugOrBrokenError
27
27
 
28
- class Comment < Token
29
- def initialize(origin, text)
30
- super(TokenType::COMMENT, origin)
31
- @text = text
28
+ class Value < Token
29
+ def initialize(value, orig_text = nil)
30
+ super(TokenType::VALUE, value.origin, orig_text)
31
+ @value = value
32
+ end
33
+
34
+ attr_reader :value
35
+
36
+ def to_s
37
+ if value.resolve_status == ResolveStatus::RESOLVED
38
+ "'#{value.unwrapped}' (#{Hocon::ConfigValueType.name(value.value_type)})"
39
+ else
40
+ "'<unresolved value>' (#{@value.value_type.name})"
41
+ end
42
+
43
+ end
44
+
45
+ def can_equal(o)
46
+ o.is_a?(Value)
47
+ end
48
+
49
+ def ==(other)
50
+ super(other) && other.value == @value
51
+ end
52
+
53
+ def hash
54
+ 41 * (41 + super) + value.hash
32
55
  end
33
- attr_reader :text
34
56
  end
35
57
 
36
- # This is not a Value, because it requires special processing
37
- class Substitution < Token
38
- def initialize(origin, optional, expression)
39
- super(TokenType::SUBSTITUTION, origin)
40
- @optional = optional
41
- @value = expression
58
+ class Line < Token
59
+ def initialize(origin)
60
+ super(TokenType::NEWLINE, origin)
61
+ end
62
+
63
+ def can_equal(other)
64
+ o.is_a?(Line)
65
+ end
66
+
67
+ def ==(other)
68
+ super(other) && other.line_number == line_number
69
+ end
70
+
71
+ def hash
72
+ 41 * (41 + super) + line_number
73
+ end
74
+
75
+ def token_text
76
+ "\n"
42
77
  end
43
78
  end
44
79
 
@@ -52,23 +87,49 @@ class Hocon::Impl::Tokens
52
87
  def to_s
53
88
  "'#{value}'"
54
89
  end
90
+
91
+ def can_equal(o)
92
+ o.is_a?(UnquotedText)
93
+ end
94
+
95
+ def ==(other)
96
+ super(other) && other.value == @value
97
+ end
98
+
99
+ def hash
100
+ 41 * (41 + super) + value.hash
101
+ end
102
+
103
+ def token_text
104
+ @value
105
+ end
55
106
  end
56
107
 
57
- class Value < Token
58
- def initialize(value)
59
- super(TokenType::VALUE, value.origin)
60
- @value = value
108
+ class IgnoredWhitespace < Token
109
+ def initialize(origin, s)
110
+ super(TokenType::IGNORED_WHITESPACE, origin)
111
+ @value = s
61
112
  end
62
113
  attr_reader :value
63
114
 
64
115
  def to_s
65
- "'#{value.unwrapped}' (#{Hocon::ConfigValueType.name(value.value_type)})"
116
+ "'#{value}' (WHITESPACE)"
66
117
  end
67
- end
68
118
 
69
- class Line < Token
70
- def initialize(origin)
71
- super(TokenType::NEWLINE, origin)
119
+ def can_equal(o)
120
+ o.is_a?(IgnoredWhitespace)
121
+ end
122
+
123
+ def ==(other)
124
+ super(other) && other.value == value
125
+ end
126
+
127
+ def hash
128
+ 41 * (41 + super) + value.hash
129
+ end
130
+
131
+ def token_text
132
+ @value
72
133
  end
73
134
  end
74
135
 
@@ -96,62 +157,189 @@ class Hocon::Impl::Tokens
96
157
  def cause
97
158
  @cause
98
159
  end
99
- end
100
160
 
101
- def self.get_problem_message(token)
102
- if token.is_a?(Problem)
103
- token.message
104
- else
105
- raise Hocon::ConfigError::ConfigBugOrBrokenError.new("tried to get problem message from #{token}", nil)
161
+ def to_s
162
+ sb = StringIO.new
163
+ sb << "'"
164
+ sb << what
165
+ sb << "'"
166
+ sb << " ("
167
+ sb << message
168
+ sb << ")"
169
+ sb.to_s
170
+ end
171
+
172
+ def can_equal(other)
173
+ other.is_a?(Problem)
174
+ end
175
+
176
+ def ==(other)
177
+ super(other) && other.what == @what &&
178
+ other.message == @message &&
179
+ other.suggest_quotes == @suggest_quotes &&
180
+ Hocon::Impl::ConfigImplUtil.equals_handling_nil?(other.cause, @cause)
181
+ end
182
+
183
+ def hash
184
+ hashcode = 41 * (41 + super)
185
+ hashcode = 41 * (hashcode + @what.hash)
186
+ hashcode = 41 * (hashcode + @message.hash)
187
+ hashcode = 41 * (hashcode + @suggest_quotes.hash)
188
+ unless @cause.nil?
189
+ hashcode = 41 * (hashcode + @cause.hash)
190
+ end
191
+
192
+ hashcode
106
193
  end
107
194
  end
108
195
 
109
- def self.get_problem_suggest_quotes(token)
110
- if token.is_a?(Problem)
111
- token.suggest_quotes
112
- else
113
- raise Hocon::ConfigError::ConfigBugOrBrokenError.new("tried to get problem suggest_quotes from #{token}", nil)
196
+ class Comment < Token
197
+ def initialize(origin, text)
198
+ super(TokenType::COMMENT, origin)
199
+ @text = text
200
+ end
201
+
202
+ class DoubleSlashComment < Comment
203
+ def initialize(origin, text)
204
+ super(origin, text)
205
+ end
206
+
207
+ def token_text
208
+ "//" + @text
209
+ end
210
+ end
211
+
212
+ class HashComment < Comment
213
+ def initialize(origin, text)
214
+ super(origin, text)
215
+ end
216
+
217
+ def token_text
218
+ "#" + @text
219
+ end
220
+ end
221
+
222
+ attr_reader :text
223
+
224
+ def to_s
225
+ sb = StringIO.new
226
+ sb << "'#"
227
+ sb << text
228
+ sb << "' (COMMENT)"
229
+ sb.string
230
+ end
231
+
232
+ def can_equal(other)
233
+ other.is_a?(Comment)
234
+ end
235
+
236
+ def ==(other)
237
+ super(other) && other.text == @text
238
+ end
239
+
240
+ def hash
241
+ hashcode = 41 * (41 + super)
242
+ hashcode = 41 * (hashcode + @text.hash)
243
+
244
+ hashcode
114
245
  end
115
246
  end
116
247
 
117
- def self.get_problem_cause(token)
118
- if token.is_a?(Problem)
119
- token.cause
120
- else
121
- raise Hocon::ConfigError::ConfigBugOrBrokenError.new("tried to get problem cause from #{token}", nil)
248
+ # This is not a Value, because it requires special processing
249
+ class Substitution < Token
250
+ def initialize(origin, optional, expression)
251
+ super(TokenType::SUBSTITUTION, origin)
252
+ @optional = optional
253
+ @value = expression
254
+ end
255
+
256
+ def optional?
257
+ @optional
258
+ end
259
+
260
+ attr_reader :value
261
+
262
+ def token_text
263
+ sub_text = ""
264
+ @value.each { |t| sub_text << t.token_text }
265
+ "${" + (@optional ? "?" : "") + sub_text + "}"
266
+ end
267
+
268
+ def to_s
269
+ sb = StringIO.new
270
+ value.each do |t|
271
+ sb << t.to_s
272
+ end
273
+ "'${#{sb.to_s}}'"
274
+ end
275
+
276
+ def can_equal(other)
277
+ other.is_a?(Substitution)
278
+ end
279
+
280
+ def ==(other)
281
+ super(other) && other.value == @value
282
+ end
283
+
284
+ def hash
285
+ 41 * (41 + super + @value.hash)
122
286
  end
123
287
  end
124
288
 
125
- def self.new_line(origin)
126
- Line.new(origin)
289
+ def self.value?(token)
290
+ token.is_a?(Value)
127
291
  end
128
292
 
129
- def self.new_problem(origin, what, message, suggest_quotes, cause)
130
- Problem.new(origin, what, message, suggest_quotes, cause)
293
+ def self.value(token)
294
+ if token.is_a?(Value)
295
+ token.value
296
+ else
297
+ raise ConfigBugOrBrokenError, "tried to get value of non-value token #{token}"
298
+ end
131
299
  end
132
300
 
133
- def self.new_comment(origin, text)
134
- Comment.new(origin, text)
301
+ def self.value_with_type?(t, value_type)
302
+ value?(t) && (value(t).value_type == value_type)
135
303
  end
136
304
 
137
- def self.new_unquoted_text(origin, s)
138
- UnquotedText.new(origin, s)
305
+ def self.newline?(t)
306
+ t.is_a?(Line)
139
307
  end
140
308
 
141
- def self.new_value(value)
142
- Value.new(value)
309
+ def self.problem?(t)
310
+ t.is_a?(Problem)
143
311
  end
144
312
 
145
- def self.new_string(origin, value)
146
- new_value(ConfigString.new(origin, value))
313
+ def self.get_problem_what(token)
314
+ if token.is_a?(Problem)
315
+ token.what
316
+ else
317
+ raise ConfigBugOrBrokenError, "tried to get problem what from #{token}"
318
+ end
147
319
  end
148
320
 
149
- def self.new_long(origin, value, original_text)
150
- new_value(ConfigNumber.new_number(origin, value, original_text))
321
+ def self.get_problem_message(token)
322
+ if token.is_a?(Problem)
323
+ token.message
324
+ else
325
+ raise ConfigBugOrBrokenError.new("tried to get problem message from #{token}")
326
+ end
151
327
  end
152
328
 
153
- def self.new_boolean(origin, value)
154
- new_value(ConfigBoolean.new(origin, value))
329
+ def self.get_problem_suggest_quotes(token)
330
+ if token.is_a?(Problem)
331
+ token.suggest_quotes
332
+ else
333
+ raise ConfigBugOrBrokenError.new("tried to get problem suggest_quotes from #{token}")
334
+ end
335
+ end
336
+
337
+ def self.get_problem_cause(token)
338
+ if token.is_a?(Problem)
339
+ token.cause
340
+ else
341
+ raise ConfigBugOrBrokenError.new("tried to get problem cause from #{token}")
342
+ end
155
343
  end
156
344
 
157
345
  def self.comment?(t)
@@ -162,14 +350,10 @@ class Hocon::Impl::Tokens
162
350
  if comment?(token)
163
351
  token.text
164
352
  else
165
- raise ConfigBugError, "tried to get comment text from #{token}"
353
+ raise ConfigBugOrBrokenError, "tried to get comment text from #{token}"
166
354
  end
167
355
  end
168
356
 
169
- def self.substitution?(t)
170
- t.is_a?(Substitution)
171
- end
172
-
173
357
  def self.unquoted_text?(token)
174
358
  token.is_a?(UnquotedText)
175
359
  end
@@ -178,31 +362,98 @@ class Hocon::Impl::Tokens
178
362
  if unquoted_text?(token)
179
363
  token.value
180
364
  else
181
- raise ConfigBugError, "tried to get unquoted text from #{token}"
365
+ raise ConfigBugOrBrokenError, "tried to get unquoted text from #{token}"
182
366
  end
183
367
  end
184
368
 
185
- def self.value?(token)
186
- token.is_a?(Value)
369
+ def self.ignored_whitespace?(token)
370
+ token.is_a?(IgnoredWhitespace)
187
371
  end
188
372
 
189
- def self.value(token)
190
- if token.is_a?(Value)
373
+ def self.substitution?(token)
374
+ token.is_a?(Substitution)
375
+ end
376
+
377
+ def self.get_substitution_path_expression(token)
378
+ if token.is_a?(Substitution)
191
379
  token.value
192
380
  else
193
- raise ConfigBugError, "tried to get value of non-value token #{token}"
381
+ raise ConfigBugOrBrokenError, "tried to get substitution from #{token}"
194
382
  end
195
383
  end
196
384
 
197
- def self.value_with_type?(t, value_type)
198
- value?(t) && (value(t).value_type == value_type)
385
+ def self.get_substitution_optional(token)
386
+ if token.is_a?(Substitution)
387
+ token.optional?
388
+ else
389
+ raise ConfigBugOrBrokenError, "tried to get substitution optionality from #{token}"
390
+ end
199
391
  end
200
392
 
201
- def self.newline?(t)
202
- t.is_a?(Line)
393
+ START = Token.new_without_origin(TokenType::START, "start of file", "")
394
+ EOF = Token.new_without_origin(TokenType::EOF, "end of file", "")
395
+ COMMA = Token.new_without_origin(TokenType::COMMA, "','", ",")
396
+ EQUALS = Token.new_without_origin(TokenType::EQUALS, "'='", "=")
397
+ COLON = Token.new_without_origin(TokenType::COLON, "':'", ":")
398
+ OPEN_CURLY = Token.new_without_origin(TokenType::OPEN_CURLY, "'{'", "{")
399
+ CLOSE_CURLY = Token.new_without_origin(TokenType::CLOSE_CURLY, "'}'", "}")
400
+ OPEN_SQUARE = Token.new_without_origin(TokenType::OPEN_SQUARE, "'['", "[")
401
+ CLOSE_SQUARE = Token.new_without_origin(TokenType::CLOSE_SQUARE, "']'", "]")
402
+ PLUS_EQUALS = Token.new_without_origin(TokenType::PLUS_EQUALS, "'+='", "+=")
403
+
404
+ def self.new_line(origin)
405
+ Line.new(origin)
203
406
  end
204
407
 
205
- def self.problem?(t)
206
- t.is_a?(Problem)
408
+ def self.new_problem(origin, what, message, suggest_quotes, cause)
409
+ Problem.new(origin, what, message, suggest_quotes, cause)
410
+ end
411
+
412
+ def self.new_comment_double_slash(origin, text)
413
+ Comment::DoubleSlashComment.new(origin, text)
414
+ end
415
+
416
+ def self.new_comment_hash(origin, text)
417
+ Comment::HashComment.new(origin, text)
418
+ end
419
+
420
+ def self.new_unquoted_text(origin, s)
421
+ UnquotedText.new(origin, s)
422
+ end
423
+
424
+ def self.new_ignored_whitespace(origin, s)
425
+ IgnoredWhitespace.new(origin, s)
426
+ end
427
+
428
+ def self.new_substitution(origin, optional, expression)
429
+ Substitution.new(origin, optional, expression)
430
+ end
431
+
432
+ def self.new_value(value, orig_text = nil)
433
+ Value.new(value, orig_text)
434
+ end
435
+
436
+ def self.new_string(origin, value, orig_text)
437
+ new_value(ConfigString::Quoted.new(origin, value), orig_text)
438
+ end
439
+
440
+ def self.new_int(origin, value, orig_text)
441
+ new_value(ConfigNumber.new_number(origin, value, orig_text), orig_text)
442
+ end
443
+
444
+ def self.new_double(origin, value, orig_text)
445
+ new_value(ConfigNumber.new_number(origin, value, orig_text), orig_text)
446
+ end
447
+
448
+ def self.new_long(origin, value, orig_text)
449
+ new_value(ConfigNumber.new_number(origin, value, orig_text), orig_text)
450
+ end
451
+
452
+ def self.new_null(origin)
453
+ new_value(ConfigNull.new(origin), "null")
454
+ end
455
+
456
+ def self.new_boolean(origin, value)
457
+ new_value(ConfigBoolean.new(origin, value), value.to_s)
207
458
  end
208
459
  end