Skip to content

Commit 39fbf01

Browse files
committed
Fixing TOML ArrayTable parsing issues #1758
1 parent 306dc93 commit 39fbf01

File tree

2 files changed

+57
-23
lines changed

2 files changed

+57
-23
lines changed

pkg/yqlib/decoder_toml.go

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,14 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
267267
fullPath := dec.getFullPath(currentNode.Child())
268268
log.Debug("fullpath: %v", fullPath)
269269

270+
c := Context{}
271+
c = c.SingleChildContext(dec.rootMap)
272+
273+
fullPath, err := getPathToUse(fullPath, dec, c)
274+
if err != nil {
275+
return false, err
276+
}
277+
270278
tableNodeValue := &CandidateNode{
271279
Kind: MappingNode,
272280
Tag: "!!map",
@@ -275,7 +283,6 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
275283

276284
var tableValue *toml.Node
277285
runAgainstCurrentExp := false
278-
var err error
279286
hasValue := dec.parser.NextExpression()
280287
// check to see if there is any table data
281288
if hasValue {
@@ -292,8 +299,6 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
292299
}
293300
}
294301

295-
c := Context{}
296-
c = c.SingleChildContext(dec.rootMap)
297302
err = dec.d.DeeplyAssign(c, fullPath, tableNodeValue)
298303
if err != nil {
299304
return false, err
@@ -324,35 +329,17 @@ func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode
324329
}
325330

326331
func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error) {
327-
log.Debug("c")
332+
log.Debug("Enter processArrayTable")
328333
fullPath := dec.getFullPath(currentNode.Child())
329334
log.Debug("Fullpath: %v", fullPath)
330335

331336
c := Context{}
332337
c = c.SingleChildContext(dec.rootMap)
333338

334-
pathToCheck := fullPath
335-
if len(fullPath) >= 1 {
336-
pathToCheck = fullPath[:len(fullPath)-1]
337-
}
338-
339-
// if fullPath points to an array of maps rather than a map
340-
// then it should set this element into the _last_ element of that array.
341-
// Because TOML. So we'll inject the last index into the path.
342-
readOp := createTraversalTree(pathToCheck, traversePreferences{DontAutoCreate: true}, false)
343-
344-
resultContext, err := dec.d.GetMatchingNodes(c, readOp)
339+
fullPath, err := getPathToUse(fullPath, dec, c)
345340
if err != nil {
346341
return false, err
347342
}
348-
if resultContext.MatchingNodes.Len() >= 1 {
349-
match := resultContext.MatchingNodes.Front().Value.(*CandidateNode)
350-
// path refers to an array, we need to add this to the last element in the array
351-
if match.Kind == SequenceNode {
352-
fullPath = append(pathToCheck, len(match.Content)-1, fullPath[len(fullPath)-1])
353-
log.Debugf("Adding to end of %v array, using path: %v", pathToCheck, fullPath)
354-
}
355-
}
356343

357344
// need to use the array append exp to add another entry to
358345
// this array: fullpath += [ thing ]
@@ -382,3 +369,29 @@ func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error)
382369

383370
return runAgainstCurrentExp, err
384371
}
372+
373+
// if fullPath points to an array of maps rather than a map
374+
// then it should set this element into the _last_ element of that array.
375+
// Because TOML. So we'll inject the last index into the path.
376+
377+
func getPathToUse(fullPath []interface{}, dec *tomlDecoder, c Context) ([]interface{}, error) {
378+
pathToCheck := fullPath
379+
if len(fullPath) >= 1 {
380+
pathToCheck = fullPath[:len(fullPath)-1]
381+
}
382+
readOp := createTraversalTree(pathToCheck, traversePreferences{DontAutoCreate: true}, false)
383+
384+
resultContext, err := dec.d.GetMatchingNodes(c, readOp)
385+
if err != nil {
386+
return nil, err
387+
}
388+
if resultContext.MatchingNodes.Len() >= 1 {
389+
match := resultContext.MatchingNodes.Front().Value.(*CandidateNode)
390+
// path refers to an array, we need to add this to the last element in the array
391+
if match.Kind == SequenceNode {
392+
fullPath = append(pathToCheck, len(match.Content)-1, fullPath[len(fullPath)-1])
393+
log.Debugf("Adding to end of %v array, using path: %v", pathToCheck, fullPath)
394+
}
395+
}
396+
return fullPath, err
397+
}

pkg/yqlib/toml_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,20 @@ var emptyArrayTableThenTableExpected = `fruits:
9595
animals: {}
9696
`
9797

98+
var arrayTableThenArray = `
99+
[[rootA.kidB]]
100+
cat = "meow"
101+
102+
[rootA.kidB.kidC]
103+
dog = "bark"`
104+
105+
var arrayTableThenArrayExpected = `rootA:
106+
kidB:
107+
- cat: meow
108+
kidC:
109+
dog: bark
110+
`
111+
98112
var sampleArrayTable = `
99113
[owner.contact]
100114
name = "Tom Preston-Werner"
@@ -341,6 +355,13 @@ var tomlScenarios = []formatScenario{
341355
expected: emptyArrayTableThenTableExpected,
342356
scenarioType: "decode",
343357
},
358+
{
359+
skipDoc: true,
360+
description: "Parse: Array of Array Table; then table",
361+
input: arrayTableThenArray,
362+
expected: arrayTableThenArrayExpected,
363+
scenarioType: "decode",
364+
},
344365
{
345366
description: "Parse: Empty Table",
346367
input: emptyTable,

0 commit comments

Comments
 (0)