diff --git a/pkg/yqlib/decoder_toml.go b/pkg/yqlib/decoder_toml.go index 3299aaf3..6c2fb34c 100644 --- a/pkg/yqlib/decoder_toml.go +++ b/pkg/yqlib/decoder_toml.go @@ -267,6 +267,14 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) { fullPath := dec.getFullPath(currentNode.Child()) log.Debug("fullpath: %v", fullPath) + c := Context{} + c = c.SingleChildContext(dec.rootMap) + + fullPath, err := getPathToUse(fullPath, dec, c) + if err != nil { + return false, err + } + tableNodeValue := &CandidateNode{ Kind: MappingNode, Tag: "!!map", @@ -275,7 +283,6 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) { var tableValue *toml.Node runAgainstCurrentExp := false - var err error hasValue := dec.parser.NextExpression() // check to see if there is any table data if hasValue { @@ -292,8 +299,6 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) { } } - c := Context{} - c = c.SingleChildContext(dec.rootMap) err = dec.d.DeeplyAssign(c, fullPath, tableNodeValue) if err != nil { return false, err @@ -324,35 +329,17 @@ func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode } func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error) { - log.Debug("c") + log.Debug("Enter processArrayTable") fullPath := dec.getFullPath(currentNode.Child()) log.Debug("Fullpath: %v", fullPath) c := Context{} c = c.SingleChildContext(dec.rootMap) - pathToCheck := fullPath - if len(fullPath) >= 1 { - pathToCheck = fullPath[:len(fullPath)-1] - } - - // if fullPath points to an array of maps rather than a map - // then it should set this element into the _last_ element of that array. - // Because TOML. So we'll inject the last index into the path. - readOp := createTraversalTree(pathToCheck, traversePreferences{DontAutoCreate: true}, false) - - resultContext, err := dec.d.GetMatchingNodes(c, readOp) + fullPath, err := getPathToUse(fullPath, dec, c) if err != nil { return false, err } - if resultContext.MatchingNodes.Len() >= 1 { - match := resultContext.MatchingNodes.Front().Value.(*CandidateNode) - // path refers to an array, we need to add this to the last element in the array - if match.Kind == SequenceNode { - fullPath = append(pathToCheck, len(match.Content)-1, fullPath[len(fullPath)-1]) - log.Debugf("Adding to end of %v array, using path: %v", pathToCheck, fullPath) - } - } // need to use the array append exp to add another entry to // this array: fullpath += [ thing ] @@ -382,3 +369,29 @@ func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error) return runAgainstCurrentExp, err } + +// if fullPath points to an array of maps rather than a map +// then it should set this element into the _last_ element of that array. +// Because TOML. So we'll inject the last index into the path. + +func getPathToUse(fullPath []interface{}, dec *tomlDecoder, c Context) ([]interface{}, error) { + pathToCheck := fullPath + if len(fullPath) >= 1 { + pathToCheck = fullPath[:len(fullPath)-1] + } + readOp := createTraversalTree(pathToCheck, traversePreferences{DontAutoCreate: true}, false) + + resultContext, err := dec.d.GetMatchingNodes(c, readOp) + if err != nil { + return nil, err + } + if resultContext.MatchingNodes.Len() >= 1 { + match := resultContext.MatchingNodes.Front().Value.(*CandidateNode) + // path refers to an array, we need to add this to the last element in the array + if match.Kind == SequenceNode { + fullPath = append(pathToCheck, len(match.Content)-1, fullPath[len(fullPath)-1]) + log.Debugf("Adding to end of %v array, using path: %v", pathToCheck, fullPath) + } + } + return fullPath, err +} diff --git a/pkg/yqlib/toml_test.go b/pkg/yqlib/toml_test.go index 255a3c8a..c9c22f4a 100644 --- a/pkg/yqlib/toml_test.go +++ b/pkg/yqlib/toml_test.go @@ -95,6 +95,20 @@ var emptyArrayTableThenTableExpected = `fruits: animals: {} ` +var arrayTableThenArray = ` +[[rootA.kidB]] +cat = "meow" + +[rootA.kidB.kidC] +dog = "bark"` + +var arrayTableThenArrayExpected = `rootA: + kidB: + - cat: meow + kidC: + dog: bark +` + var sampleArrayTable = ` [owner.contact] name = "Tom Preston-Werner" @@ -341,6 +355,13 @@ var tomlScenarios = []formatScenario{ expected: emptyArrayTableThenTableExpected, scenarioType: "decode", }, + { + skipDoc: true, + description: "Parse: Array of Array Table; then table", + input: arrayTableThenArray, + expected: arrayTableThenArrayExpected, + scenarioType: "decode", + }, { description: "Parse: Empty Table", input: emptyTable,