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.
- checksums.yaml +7 -0
- data/README.md +4 -2
- data/lib/hocon.rb +2 -0
- data/lib/hocon/config.rb +1010 -0
- data/lib/hocon/config_error.rb +32 -2
- data/lib/hocon/config_factory.rb +46 -0
- data/lib/hocon/config_include_context.rb +49 -0
- data/lib/hocon/config_includer_file.rb +27 -0
- data/lib/hocon/config_list.rb +49 -0
- data/lib/hocon/config_mergeable.rb +74 -0
- data/lib/hocon/config_object.rb +144 -1
- data/lib/hocon/config_parse_options.rb +33 -9
- data/lib/hocon/config_parseable.rb +51 -0
- data/lib/hocon/config_render_options.rb +4 -2
- data/lib/hocon/config_resolve_options.rb +31 -0
- data/lib/hocon/config_syntax.rb +5 -2
- data/lib/hocon/config_util.rb +73 -0
- data/lib/hocon/config_value.rb +122 -0
- data/lib/hocon/config_value_factory.rb +66 -2
- data/lib/hocon/config_value_type.rb +5 -2
- data/lib/hocon/impl.rb +2 -0
- data/lib/hocon/impl/abstract_config_node.rb +29 -0
- data/lib/hocon/impl/abstract_config_node_value.rb +11 -0
- data/lib/hocon/impl/abstract_config_object.rb +148 -42
- data/lib/hocon/impl/abstract_config_value.rb +251 -11
- data/lib/hocon/impl/array_iterator.rb +19 -0
- data/lib/hocon/impl/config_boolean.rb +7 -1
- data/lib/hocon/impl/config_concatenation.rb +177 -28
- data/lib/hocon/impl/config_delayed_merge.rb +329 -0
- data/lib/hocon/impl/config_delayed_merge_object.rb +274 -0
- data/lib/hocon/impl/config_document_parser.rb +647 -0
- data/lib/hocon/impl/config_double.rb +44 -0
- data/lib/hocon/impl/config_impl.rb +143 -19
- data/lib/hocon/impl/config_impl_util.rb +18 -0
- data/lib/hocon/impl/config_include_kind.rb +10 -0
- data/lib/hocon/impl/config_int.rb +13 -1
- data/lib/hocon/impl/config_node_array.rb +11 -0
- data/lib/hocon/impl/config_node_comment.rb +19 -0
- data/lib/hocon/impl/config_node_complex_value.rb +54 -0
- data/lib/hocon/impl/config_node_concatenation.rb +11 -0
- data/lib/hocon/impl/config_node_field.rb +81 -0
- data/lib/hocon/impl/config_node_include.rb +33 -0
- data/lib/hocon/impl/config_node_object.rb +276 -0
- data/lib/hocon/impl/config_node_path.rb +48 -0
- data/lib/hocon/impl/config_node_root.rb +60 -0
- data/lib/hocon/impl/config_node_simple_value.rb +42 -0
- data/lib/hocon/impl/config_node_single_token.rb +17 -0
- data/lib/hocon/impl/config_null.rb +15 -7
- data/lib/hocon/impl/config_number.rb +43 -4
- data/lib/hocon/impl/config_parser.rb +403 -0
- data/lib/hocon/impl/config_reference.rb +142 -0
- data/lib/hocon/impl/config_string.rb +55 -7
- data/lib/hocon/impl/container.rb +29 -0
- data/lib/hocon/impl/default_transformer.rb +24 -15
- data/lib/hocon/impl/from_map_mode.rb +3 -1
- data/lib/hocon/impl/full_includer.rb +2 -0
- data/lib/hocon/impl/memo_key.rb +42 -0
- data/lib/hocon/impl/mergeable_value.rb +8 -0
- data/lib/hocon/impl/origin_type.rb +8 -2
- data/lib/hocon/impl/parseable.rb +455 -91
- data/lib/hocon/impl/path.rb +181 -59
- data/lib/hocon/impl/path_builder.rb +24 -3
- data/lib/hocon/impl/path_parser.rb +280 -0
- data/lib/hocon/impl/replaceable_merge_stack.rb +22 -0
- data/lib/hocon/impl/resolve_context.rb +254 -0
- data/lib/hocon/impl/resolve_memos.rb +21 -0
- data/lib/hocon/impl/resolve_result.rb +39 -0
- data/lib/hocon/impl/resolve_source.rb +354 -0
- data/lib/hocon/impl/resolve_status.rb +3 -1
- data/lib/hocon/impl/simple_config.rb +264 -10
- data/lib/hocon/impl/simple_config_document.rb +48 -0
- data/lib/hocon/impl/simple_config_list.rb +282 -8
- data/lib/hocon/impl/simple_config_object.rb +424 -88
- data/lib/hocon/impl/simple_config_origin.rb +263 -71
- data/lib/hocon/impl/simple_include_context.rb +31 -1
- data/lib/hocon/impl/simple_includer.rb +196 -1
- data/lib/hocon/impl/substitution_expression.rb +38 -0
- data/lib/hocon/impl/token.rb +17 -4
- data/lib/hocon/impl/token_type.rb +6 -2
- data/lib/hocon/impl/tokenizer.rb +339 -109
- data/lib/hocon/impl/tokens.rb +330 -79
- data/lib/hocon/impl/unmergeable.rb +14 -1
- data/lib/hocon/impl/unsupported_operation_error.rb +6 -0
- data/lib/hocon/impl/url.rb +37 -0
- data/lib/hocon/parser.rb +7 -0
- data/lib/hocon/parser/config_document.rb +92 -0
- data/lib/hocon/parser/config_document_factory.rb +36 -0
- data/lib/hocon/parser/config_node.rb +30 -0
- metadata +67 -43
- data/lib/hocon/impl/config_float.rb +0 -13
- data/lib/hocon/impl/parser.rb +0 -977
- data/lib/hocon/impl/properties_parser.rb +0 -83
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'hocon/impl'
|
4
|
+
require 'hocon/config_error'
|
5
|
+
require 'hocon/impl/abstract_config_node'
|
6
|
+
require 'hocon/impl/abstract_config_node_value'
|
7
|
+
require 'hocon/impl/config_node_comment'
|
8
|
+
require 'hocon/impl/config_node_path'
|
9
|
+
require 'hocon/impl/config_node_single_token'
|
10
|
+
require 'hocon/impl/tokens'
|
11
|
+
|
12
|
+
class Hocon::Impl::ConfigNodeField
|
13
|
+
include Hocon::Impl::AbstractConfigNode
|
14
|
+
|
15
|
+
Tokens = Hocon::Impl::Tokens
|
16
|
+
|
17
|
+
def initialize(children)
|
18
|
+
@children = children
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :children
|
22
|
+
|
23
|
+
def tokens
|
24
|
+
tokens = []
|
25
|
+
@children.each do |child|
|
26
|
+
tokens += child.tokens
|
27
|
+
end
|
28
|
+
tokens
|
29
|
+
end
|
30
|
+
|
31
|
+
def replace_value(new_value)
|
32
|
+
children_copy = @children.clone
|
33
|
+
children_copy.each_with_index do |child, i|
|
34
|
+
if child.is_a?(Hocon::Impl::AbstractConfigNodeValue)
|
35
|
+
children_copy[i] = new_value
|
36
|
+
return self.class.new(children_copy)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
raise Hocon::ConfigError::ConfigBugOrBrokenError, "Field node doesn't have a value"
|
40
|
+
end
|
41
|
+
|
42
|
+
def value
|
43
|
+
@children.each do |child|
|
44
|
+
if child.is_a?(Hocon::Impl::AbstractConfigNodeValue)
|
45
|
+
return child
|
46
|
+
end
|
47
|
+
end
|
48
|
+
raise Hocon::ConfigError::ConfigBugOrBrokenError, "Field node doesn't have a value"
|
49
|
+
end
|
50
|
+
|
51
|
+
def path
|
52
|
+
@children.each do |child|
|
53
|
+
if child.is_a?(Hocon::Impl::ConfigNodePath)
|
54
|
+
return child
|
55
|
+
end
|
56
|
+
end
|
57
|
+
raise Hocon::ConfigError::ConfigBugOrBrokenError, "Field node doesn't have a path"
|
58
|
+
end
|
59
|
+
|
60
|
+
def separator
|
61
|
+
@children.each do |child|
|
62
|
+
if child.is_a?(Hocon::Impl::ConfigNodeSingleToken)
|
63
|
+
t = child.token
|
64
|
+
if t == Tokens::PLUS_EQUALS or t == Tokens::COLON or t == Tokens::EQUALS
|
65
|
+
return t
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def comments
|
73
|
+
comments = []
|
74
|
+
@children.each do |child|
|
75
|
+
if child.is_a?(Hocon::Impl::ConfigNodeComment)
|
76
|
+
comments << child.comment_text
|
77
|
+
end
|
78
|
+
end
|
79
|
+
comments
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'hocon/impl'
|
4
|
+
require 'hocon/config_error'
|
5
|
+
require 'hocon/impl/abstract_config_node'
|
6
|
+
require 'hocon/impl/config_node_simple_value'
|
7
|
+
|
8
|
+
class Hocon::Impl::ConfigNodeInclude
|
9
|
+
include Hocon::Impl::AbstractConfigNode
|
10
|
+
def initialize(children, kind)
|
11
|
+
@children = children
|
12
|
+
@kind = kind
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :kind, :children
|
16
|
+
|
17
|
+
def tokens
|
18
|
+
tokens = []
|
19
|
+
@children.each do |child|
|
20
|
+
tokens += child.tokens
|
21
|
+
end
|
22
|
+
tokens
|
23
|
+
end
|
24
|
+
|
25
|
+
def name
|
26
|
+
@children.each do |child|
|
27
|
+
if child.is_a?(Hocon::Impl::ConfigNodeSimpleValue)
|
28
|
+
return Hocon::Impl::Tokens.value(child.token).unwrapped
|
29
|
+
end
|
30
|
+
end
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,276 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'hocon/config_syntax'
|
4
|
+
require 'hocon/impl'
|
5
|
+
require 'hocon/impl/config_node_complex_value'
|
6
|
+
require 'hocon/impl/config_node_field'
|
7
|
+
require 'hocon/impl/config_node_single_token'
|
8
|
+
require 'hocon/impl/tokens'
|
9
|
+
|
10
|
+
class Hocon::Impl::ConfigNodeObject
|
11
|
+
include Hocon::Impl::ConfigNodeComplexValue
|
12
|
+
|
13
|
+
ConfigSyntax = Hocon::ConfigSyntax
|
14
|
+
Tokens = Hocon::Impl::Tokens
|
15
|
+
|
16
|
+
def new_node(nodes)
|
17
|
+
self.class.new(nodes)
|
18
|
+
end
|
19
|
+
|
20
|
+
def has_value(desired_path)
|
21
|
+
@children.each do |node|
|
22
|
+
if node.is_a?(Hocon::Impl::ConfigNodeField)
|
23
|
+
field = node
|
24
|
+
key = field.path.value
|
25
|
+
if key == desired_path || key.starts_with(desired_path)
|
26
|
+
return true
|
27
|
+
elsif desired_path.starts_with(key)
|
28
|
+
if field.value.is_a?(self.class)
|
29
|
+
obj = field.value
|
30
|
+
remaining_path = desired_path.sub_path_to_end(key.length)
|
31
|
+
if obj.has_value(remaining_path)
|
32
|
+
return true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
def change_value_on_path(desired_path, value, flavor)
|
42
|
+
children_copy = @children.clone
|
43
|
+
seen_non_matching = false
|
44
|
+
# Copy the value so we can change it to null but not modify the original parameter
|
45
|
+
value_copy = value
|
46
|
+
i = children_copy.size
|
47
|
+
while i >= 0 do
|
48
|
+
if children_copy[i].is_a?(Hocon::Impl::ConfigNodeSingleToken)
|
49
|
+
t = children_copy[i].token
|
50
|
+
# Ensure that, when we are removing settings in JSON, we don't end up with a trailing comma
|
51
|
+
if flavor.equal?(ConfigSyntax::JSON) && !seen_non_matching && t.equal?(Tokens::COMMA)
|
52
|
+
children_copy.delete_at(i)
|
53
|
+
end
|
54
|
+
i -= 1
|
55
|
+
next
|
56
|
+
elsif !children_copy[i].is_a?(Hocon::Impl::ConfigNodeField)
|
57
|
+
i -= 1
|
58
|
+
next
|
59
|
+
end
|
60
|
+
node = children_copy[i]
|
61
|
+
key = node.path.value
|
62
|
+
|
63
|
+
# Delete all multi-element paths that start with the desired path, since technically they are duplicates
|
64
|
+
if (value_copy.nil? && key == desired_path) || (key.starts_with(desired_path) && !(key == desired_path))
|
65
|
+
children_copy.delete_at(i)
|
66
|
+
# Remove any whitespace or commas after the deleted setting
|
67
|
+
j = i
|
68
|
+
while j < children_copy.size
|
69
|
+
if children_copy[j].is_a?(Hocon::Impl::ConfigNodeSingleToken)
|
70
|
+
t = children_copy[j].token
|
71
|
+
if Tokens.ignored_whitespace?(t) || t.equal?(Tokens::COMMA)
|
72
|
+
children_copy.delete_at(j)
|
73
|
+
j -= 1
|
74
|
+
else
|
75
|
+
break
|
76
|
+
end
|
77
|
+
else
|
78
|
+
break
|
79
|
+
end
|
80
|
+
j += 1
|
81
|
+
end
|
82
|
+
elsif key == desired_path
|
83
|
+
seen_non_matching = true
|
84
|
+
before = i - 1 > 0 ? children_copy[i - 1] : nil
|
85
|
+
if value.is_a?(Hocon::Impl::ConfigNodeComplexValue) && before.is_a?(Hocon::Impl::ConfigNodeSingleToken) &&
|
86
|
+
Tokens.ignored_whitespace?(before.token)
|
87
|
+
indented_value = value.indent_text(before)
|
88
|
+
else
|
89
|
+
indented_value = value
|
90
|
+
end
|
91
|
+
children_copy[i] = node.replace_value(indented_value)
|
92
|
+
value_copy = nil
|
93
|
+
elsif desired_path.starts_with(key)
|
94
|
+
seen_non_matching = true
|
95
|
+
if node.value.is_a?(self.class)
|
96
|
+
remaining_path = desired_path.sub_path_to_end(key.length)
|
97
|
+
children_copy[i] = node.replace_value(node.value.change_value_on_path(remaining_path, value_copy, flavor))
|
98
|
+
if !value_copy.nil? && !(node == @children[i])
|
99
|
+
value_copy = nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
else
|
103
|
+
seen_non_matching = true
|
104
|
+
end
|
105
|
+
i -= 1
|
106
|
+
end
|
107
|
+
self.class.new(children_copy)
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_value_on_path(desired_path, value, flavor = ConfigSyntax::CONF)
|
111
|
+
path = Hocon::Impl::PathParser.parse_path_node(desired_path, flavor)
|
112
|
+
set_value_on_path_node(path, value, flavor)
|
113
|
+
end
|
114
|
+
|
115
|
+
def set_value_on_path_node(desired_path, value, flavor)
|
116
|
+
node = change_value_on_path(desired_path.value, value, flavor)
|
117
|
+
|
118
|
+
# If the desired Path did not exist, add it
|
119
|
+
unless node.has_value(desired_path.value)
|
120
|
+
return node.add_value_on_path(desired_path, value, flavor)
|
121
|
+
end
|
122
|
+
node
|
123
|
+
end
|
124
|
+
|
125
|
+
def indentation
|
126
|
+
seen_new_line = false
|
127
|
+
indentation = []
|
128
|
+
|
129
|
+
@children.each_index do |i|
|
130
|
+
unless seen_new_line
|
131
|
+
if @children[i].is_a?(Hocon::Impl::ConfigNodeSingleToken) && Tokens.newline?(@children[i].token)
|
132
|
+
seen_new_line = true
|
133
|
+
indentation.push(Hocon::Impl::ConfigNodeSingleToken.new(Tokens.new_line(nil)))
|
134
|
+
end
|
135
|
+
else
|
136
|
+
if @children[i].is_a?(Hocon::Impl::ConfigNodeSingleToken) &&
|
137
|
+
Tokens.ignored_whitespace?(@children[i].token) &&
|
138
|
+
i + 1 < @children.size &&
|
139
|
+
(@children[i + 1].is_a?(Hocon::Impl::ConfigNodeField) || @children[i + 1].is_a?(Hocon::Impl::ConfigNodeInclude))
|
140
|
+
# Return the indentation of the first setting on its own line
|
141
|
+
indentation.push(@children[i])
|
142
|
+
return indentation
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
if indentation.empty?
|
147
|
+
indentation.push(Hocon::Impl::ConfigNodeSingleToken.new(Tokens.new_ignored_whitespace(nil, " ")))
|
148
|
+
return indentation
|
149
|
+
else
|
150
|
+
# Calculate the indentation of the ending curly-brace to get the indentation of the root object
|
151
|
+
last = @children[-1]
|
152
|
+
if last.is_a?(Hocon::Impl::ConfigNodeSingleToken) && last.token.equal?(Tokens::CLOSE_CURLY)
|
153
|
+
beforeLast = @children[-2]
|
154
|
+
if beforeLast.is_a?(Hocon::Impl::ConfigNodeSingleToken) &&
|
155
|
+
Tokens.ignored_whitespace?(beforeLast.token)
|
156
|
+
indent = beforeLast.token.token_text
|
157
|
+
indent += " "
|
158
|
+
indentation.push(Hocon::Impl::ConfigNodeSingleToken.new(Tokens.new_ignored_whitespace(nil, indent)))
|
159
|
+
return indentation
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# The object has no curly braces and is at the root level, so don't indent
|
165
|
+
indentation
|
166
|
+
end
|
167
|
+
|
168
|
+
def add_value_on_path(desired_path, value, flavor)
|
169
|
+
path = desired_path.value
|
170
|
+
children_copy = @children.clone
|
171
|
+
indentation = indentation().clone
|
172
|
+
|
173
|
+
# If the value we're inserting is a complex value, we'll need to indent it for insertion
|
174
|
+
if value.is_a?(Hocon::Impl::ConfigNodeComplexValue)
|
175
|
+
indented_value = value.indent_text(indentation[-1])
|
176
|
+
else
|
177
|
+
indented_value = value
|
178
|
+
end
|
179
|
+
same_line = !(indentation[0].is_a?(Hocon::Impl::ConfigNodeSingleToken) &&
|
180
|
+
Tokens.newline?(indentation[0].token))
|
181
|
+
|
182
|
+
# If the path is of length greater than one, see if the value needs to be added further down
|
183
|
+
if path.length > 1
|
184
|
+
(0..@children.size - 1).reverse_each do |i|
|
185
|
+
unless @children[i].is_a?(Hocon::Impl::ConfigNodeField)
|
186
|
+
next
|
187
|
+
end
|
188
|
+
node = @children[i]
|
189
|
+
key = node.path.value
|
190
|
+
if path.starts_with(key) && node.value.is_a?(self.class)
|
191
|
+
remaining_path = desired_path.sub_path(key.length)
|
192
|
+
new_value = node.value
|
193
|
+
children_copy[i] = node.replace_value(new_value.add_value_on_path(remaining_path, value, flavor))
|
194
|
+
return self.class.new(children_copy)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Otherwise, construct the new setting
|
200
|
+
starts_with_brace = @children[0].is_a?(Hocon::Impl::ConfigNodeSingleToken) && @children[0].token.equal?(Tokens::OPEN_CURLY)
|
201
|
+
new_nodes = []
|
202
|
+
new_nodes += indentation
|
203
|
+
new_nodes.push(desired_path.first)
|
204
|
+
new_nodes.push(Hocon::Impl::ConfigNodeSingleToken.new(Tokens.new_ignored_whitespace(nil, ' ')))
|
205
|
+
new_nodes.push(Hocon::Impl::ConfigNodeSingleToken.new(Tokens::COLON))
|
206
|
+
new_nodes.push(Hocon::Impl::ConfigNodeSingleToken.new(Tokens.new_ignored_whitespace(nil, ' ')))
|
207
|
+
|
208
|
+
if path.length == 1
|
209
|
+
new_nodes.push(indented_value)
|
210
|
+
else
|
211
|
+
# If the path is of length greater than one add the required new objects along the path
|
212
|
+
new_object_nodes = []
|
213
|
+
new_object_nodes.push(Hocon::Impl::ConfigNodeSingleToken.new(Tokens::OPEN_CURLY))
|
214
|
+
new_object_nodes.push(Hocon::Impl::ConfigNodeSingleToken.new(Tokens.new_ignored_whitespace(nil, ' ')))
|
215
|
+
new_object_nodes.push(Hocon::Impl::ConfigNodeSingleToken.new(Tokens::CLOSE_CURLY))
|
216
|
+
new_object = self.class.new(new_object_nodes)
|
217
|
+
new_nodes.push(new_object.add_value_on_path(desired_path.sub_path(1), indented_value, flavor))
|
218
|
+
end
|
219
|
+
|
220
|
+
# Combine these two cases so that we only have to iterate once
|
221
|
+
if flavor.equal?(ConfigSyntax::JSON) || starts_with_brace || same_line
|
222
|
+
i = children_copy.size - 1
|
223
|
+
while i >= 0
|
224
|
+
|
225
|
+
# If we are in JSON or are adding a setting on the same line, we need to add a comma to the
|
226
|
+
# last setting
|
227
|
+
if (flavor.equal?(ConfigSyntax::JSON) || same_line) && children_copy[i].is_a?(Hocon::Impl::ConfigNodeField)
|
228
|
+
if i + 1 >= children_copy.size ||
|
229
|
+
!(children_copy[i + 1].is_a?(Hocon::Impl::ConfigNodeSingleToken) && children_copy[i + 1].token.equal?(Tokens::COMMA))
|
230
|
+
children_copy.insert(i + 1, Hocon::Impl::ConfigNodeSingleToken.new(Tokens::COMMA))
|
231
|
+
break
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# Add the value into the copy of the children map, keeping any whitespace/newlines
|
236
|
+
# before the close curly brace
|
237
|
+
if starts_with_brace && children_copy[i].is_a?(Hocon::Impl::ConfigNodeSingleToken) &&
|
238
|
+
children_copy[i].token == Tokens::CLOSE_CURLY
|
239
|
+
previous = children_copy[i - 1]
|
240
|
+
if previous.is_a?(Hocon::Impl::ConfigNodeSingleToken) && Tokens.newline?(previous.token)
|
241
|
+
children_copy.insert(i - 1, Hocon::Impl::ConfigNodeField.new(new_nodes))
|
242
|
+
i -= 1
|
243
|
+
elsif previous.is_a?(Hocon::Impl::ConfigNodeSingleToken) && Tokens.ignored_whitespace?(previous.token)
|
244
|
+
before_previous = children_copy[i - 2]
|
245
|
+
if same_line
|
246
|
+
children_copy.insert(i - 1, Hocon::Impl::ConfigNodeField.new(new_nodes))
|
247
|
+
i -= 1
|
248
|
+
elsif before_previous.is_a?(Hocon::Impl::ConfigNodeSingleToken) && Tokens.newline?(before_previous.token)
|
249
|
+
children_copy.insert(i - 2, Hocon::Impl::ConfigNodeField.new(new_nodes))
|
250
|
+
i -= 2
|
251
|
+
else
|
252
|
+
children_copy.insert(i, Hocon::Impl::ConfigNodeField.new(new_nodes))
|
253
|
+
end
|
254
|
+
else
|
255
|
+
children_copy.insert(i, Hocon::Impl::ConfigNodeField.new(new_nodes))
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
i -= 1
|
260
|
+
end
|
261
|
+
end
|
262
|
+
unless starts_with_brace
|
263
|
+
if children_copy[-1].is_a?(Hocon::Impl::ConfigNodeSingleToken) && Tokens.newline?(children_copy[-1].token)
|
264
|
+
children_copy.insert(-2, Hocon::Impl::ConfigNodeField.new(new_nodes))
|
265
|
+
else
|
266
|
+
children_copy.push(Hocon::Impl::ConfigNodeField.new(new_nodes))
|
267
|
+
end
|
268
|
+
end
|
269
|
+
self.class.new(children_copy)
|
270
|
+
end
|
271
|
+
|
272
|
+
def remove_value_on_path(desired_path, flavor)
|
273
|
+
path = Hocon::Impl::PathParser.parse_path_node(desired_path, flavor).value
|
274
|
+
change_value_on_path(path, nil, flavor)
|
275
|
+
end
|
276
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'hocon/impl'
|
4
|
+
require 'hocon/impl/tokens'
|
5
|
+
require 'hocon/impl/abstract_config_node'
|
6
|
+
|
7
|
+
class Hocon::Impl::ConfigNodePath
|
8
|
+
include Hocon::Impl::AbstractConfigNode
|
9
|
+
Tokens = Hocon::Impl::Tokens
|
10
|
+
|
11
|
+
def initialize(path, tokens)
|
12
|
+
@path = path
|
13
|
+
@tokens = tokens
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :tokens
|
17
|
+
|
18
|
+
def value
|
19
|
+
@path
|
20
|
+
end
|
21
|
+
|
22
|
+
def sub_path(to_remove)
|
23
|
+
period_count = 0
|
24
|
+
tokens_copy = tokens.clone
|
25
|
+
(0..tokens_copy.size - 1).each do |i|
|
26
|
+
if Tokens.unquoted_text?(tokens_copy[i]) &&
|
27
|
+
tokens_copy[i].token_text == "."
|
28
|
+
period_count += 1
|
29
|
+
end
|
30
|
+
|
31
|
+
if period_count == to_remove
|
32
|
+
return self.class.new(@path.sub_path_to_end(to_remove), tokens_copy[i + 1..tokens_copy.size])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
raise ConfigBugOrBrokenError, "Tried to remove too many elements from a Path node"
|
36
|
+
end
|
37
|
+
|
38
|
+
def first
|
39
|
+
tokens_copy = tokens.clone
|
40
|
+
(0..tokens_copy.size - 1).each do |i|
|
41
|
+
if Tokens.unquoted_text?(tokens_copy[i]) &&
|
42
|
+
tokens_copy[i].token_text == "."
|
43
|
+
return self.class.new(@path.sub_path(0, 1), tokens_copy[0, i])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
self
|
47
|
+
end
|
48
|
+
end
|